8 Replies - 637 Views - Last Post: 04 June 2013 - 12:27 PM Rate Topic: -----

#1 xtremer360  Icon User is offline

  • D.I.C Head

Reputation: -2
  • View blog
  • Posts: 123
  • Joined: 03-March 11

Flattened Code Has Some Recursion Issue

Posted 31 May 2013 - 12:43 PM

I'm trying to figure out with my application when I submit my login form with the jquery ajax request it runs the submit function but at some point gets into a infinite loop I think. The Unflattened version works however the flattened version is what gives me the infinite loop.

The reason for flattening my code was to work on the single responsibility principal. I'm having some recursion issues from what I've been told somewhere in my flattened code.

Unflatttened

<?php 

if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Login extends Backend_Controller 
{
public function __construct()
{
    parent::__construct();
    $this->load->model('users_model');  
}

public function index()
{   
    Asset::js('theme::login.js');

    $this->template
        ->title('Login')
        ->set_layout('usermanagement')
        ->build('login');
}

public function submit($post_username = NULL, $post_password = NULL)
{
    /* Set variable defaults */
    $output_status = 'Notice';
    $output_title = 'Not Processed';
    $output_message = 'The request was unprocessed!';

    /* Number of error flags */
    $flags = 0;

    /* Set validation rules for post data */
    $this->form_validation->set_rules('username', 'Username', 'trim|required|xss_clean|min_length[6]|max_length[12]|regex_match[/[a-z0-9]/]');
    $this->form_validation->set_rules('password', 'Password', 'trim|required|xss_clean|min_length[6]|max_length[12]|regex_match[/[a-z0-9]/]');
    $this->form_validation->set_rules('remember', 'Remember Me', 'trim|xss_clean|integer');

    if ($this->form_validation->run() == TRUE)
    {
        /* Form validation passed */

        /* Post values from login form */
        $post_username = $this->input->post('username');
        $post_password = $this->input->post('password');

        /* Test to see value of posted login form */
        //echo '<pre>';
        //var_dump($post_username);
        //var_dump($post_password);
        //echo '</pre>';
        //die();

        /* Get user data from post username value */
        $user_data = $this->users_model->get_by('username', $post_username);

        /* Test to see value of $user_data */
        //echo '<pre>';
        //var_dump($user_data);
        //echo '</pre>';
        //die();

        if (count($user_data) > 0)
        {
            /* User was found in database */

            if ($user_data->lock_date !== '0000-00-00 00:00:00')
            {
                /* User is locked out */

                if (strtotime(gmdate('Y-m-d H:i:s', time())) < strtotime($user_data->lock_date))
                {
                    /* User is still locked out */
                    $output_status = 'Error';
                    $output_title = 'Account Locked';
                    $output_message = 'This user account is currently locked!';
                    $flags++;
                }
                else
                {
                    /* User can be unlocked and form be resubmitted */
                    $this->users_model->unlock_user($user_data->user_id);
                    $this->submit($post_username, $post_password);
                    return FALSE;
                }

            }

            if ($flags == 0)
            {
                /* User is not locked out and no error messages reported */

                /* Match user status */
                switch ($user_data->user_status_id) 
                {
                    case 1:
                        $output_status = 'Error';
                        $output_title = 'Account Unverified';
                        $output_message = 'Sorry you must verify your account before logging in!';
                        $flags++;
                        break;
                    case 3:
                        $output_status = 'Error';
                        $output_title = 'Account Suspended';
                        $output_message = 'Your account has been suspended!';
                        $flags++;
                        break;
                    case 4:
                        $output_status = 'Error';
                        $output_title = 'Account Banned';
                        $output_message = 'Your account has been banned!';
                        $flags++;
                        break;
                    case 5:
                        $output_status = 'Error';
                        $output_title = 'Account Deleted';
                        $output_message = 'Your account has been deleted!';
                        $flags++;
                        break;
                }

                if ($flags == 0)
                {
                    /* User is registered and validated and no error messages reported */                   
                    $regenerated_post_password = $this->genfunc->reGenPassHash($post_password, $user_data->password_hash);

                    $failed_logins = $this->session->userdata('failed_logins');

                    if ($regenerated_post_password == $user_data->password)
                    {
                        /* Password from login form matches user stored password */

                        /* Start session with user id and clear previous failed login attempts */
                        $this->session->set_userdata('uid', $user_data->user_id);
                        $this->session->unset_userdata('failed_logins');
                        $this->users_model->insert_session($user_data->user_id, gmdate('Y-m-d H:i:s', time()));
                        $output_status = 'Success';
                        $output_title = 'Login Success';
                        $output_message = 'Successful login! Sending you to the dashboard';
                    }
                    else
                    {
                        /* Password from login from does not match user stored password */
                        if ($failed_logins > 0)
                        {
                            /* User has atleast one failed login attempt for the current session */
                            if ($failed_logins == 4)
                            {      
                                $this->users_model->lock_out_user($user_data->user_id, gmdate('Y-m-d H:i:s', time()+(60*15)));
                                //$this->functions_model->send_email('maximum_failed_login_attempts_exceeded', $user_data->email_address, $user_data)
                                $output_status = 'Error';
                                $output_title = 'Account Locked';
                                $output_message = 'Your account is currently locked, we apologize for the inconvienence. You must wait 15 minutes before you can log in again! An email was sent to the owner of this account! Forgotten your username or password? <a href="forgotusername">Forgot Username</a> or <a href="forgotpassword">Forgot Password</a>';
                            }
                            else
                            {
                                /* User has a few more chances to get password right */
                                $failed_logins++;
                                $this->session->set_userdata('failed_logins', $failed_logins);
                                $output_status = 'Error';
                                $output_title = 'Incorrect Login Credentials';
                                $output_message = 'Incorrect username and password credentials!';
                            }
                        }
                        else
                        {
                            /* First time user has not entered username and password successfully */
                            $this->session->set_userdata('failed_logins', 1);
                            $output_status = 'Error';
                            $output_title = 'Incorrect Login Credentials';
                            $output_message = 'Incorrect username and password credentials!';
                        }

                        $this->users_model->increase_login_attempt($this->input->ip_address(), $post_username, gmdate('Y-m-d H:i:s', time()));
                    }
                }
            }
        }
        else
        {
            /* User was not found in database */
            $output_status = 'Error';
            $output_title = 'User Not Found';
            $output_message = 'The user was not found in the database!';
        }
    }
    else
    {

        /* Form validation failed */
        $output_status = 'Error';
        $output_title = 'Form Not Validated';
        $output_message = 'The form did not validate successfully!';
    }

    $output_array = array('output_status' => $output_status, 'output_title' => $output_title, 'output_message' => $output_message);

    echo json_encode($output_array);
}
}



Flattened

<?php

if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Loginag extends Backend_Controller
{
public function __construct()
{
    parent::__construct();
    $this->load->model('users_model');
}

public function index()
{
    Asset::js('theme::loginag.js');

    $this->template
    ->title('Login')
    ->set_layout('usermanagement')
    ->build('login');
}

public function form_is_valid()
{
    /* Set validation rules for post data */
    $this->form_validation->set_rules('username', 'Username', 'trim|required|xss_clean|min_length[6]|max_length[12]|regex_match[/[a-z0-9]/]');
    $this->form_validation->set_rules('password', 'Password', 'trim|required|xss_clean|min_length[6]|max_length[12]|regex_match[/[a-z0-9]/]');
    $this->form_validation->set_rules('remember', 'Remember Me', 'trim|xss_clean|integer');

    /* Form validation passed */
    return $this->form_validation->run();
}

public function is_user_locked($user_data)
{
    if ($user_data->lock_date !== '0000-00-00 00:00:00')
    {
        /* User is locked out */

        if (strtotime(gmdate('Y-m-d H:i:s', time())) < strtotime($user_data->lock_date))
        {
            /* User is still locked out */
            return TRUE;
        }
        else
        {
            /* User is no longer locked out */
            return FALSE;
        }

    }
}

public function check_user_status($user_data)
{
    /* Match user status */
    switch ($user_data->user_status_id)
    {
    case 1:
        $this->output('Sorry you must verify your account before logging in!', 'Account Unverified', 'Error');
        break;
    case 3:
        $this->output('Your account has been suspended!', 'Account Suspended', 'Error');
        break;
    case 4:
        $this->output('Your account has been suspended!', 'Account Banned', 'Error');
        break;
    case 5:
        $this->output('Your account has been deleted!', 'Account Deleted', 'Error');
        break;
    default:
        return;
    }
}

public function output($message, $title, $status = 'Success')
{
    switch ($status)
    {
    case 'Error':
        array('status' => 'Error');
        break;
    case 'Notice':
        array('status' => 'Notice');
        break;
    case 'Success':
        array('status' => 'Success');
        break;
    }
    echo json_encode($status, $title, $message);
}

public function start_user_session()
{
    /* Start session with user id and clear previous failed login attempts */
    $this->session->set_userdata('uid', $user_data->user_id);
    $this->session->unset_userdata('failed_logins');
    $this->users_model->insert_session($user_data->user_id, gmdate('Y-m-d H:i:s', time()));
    return;
}

public function submit($post_username = NULL, $post_password = NULL)
{
    if (!$this->form_is_valid())
    {
        $this->output('The form did not validate successfully!', 'Form Not Validated', 'Error');
        return;
    }

    /* Post values from login form */
    $post_username = $this->input->post('username');
    $post_password = $this->input->post('password');

    /* Test to see value of posted login form */
    //echo '<pre>';
    //var_dump($post_username);
    //var_dump($post_password);
    //echo '</pre>';
    //die();

    /* Get user data from post username value */
    $user_data = $this->users_model->get_by('username', $post_username);

    /* Test to see value of $user_data */
    //echo '<pre>';
    //var_dump($user_data);
    //echo '</pre>';
    //die();

    if (count($user_data) == 0)
    {
        /* User was not found in database */
        $this->output('The user was not found in the database!', 'User Not Found', 'Error');
        return;
    }

    /* User was found in database */

    if ($this->is_user_locked($user_data->lock_date))
    {
        /* User is locked from logging in from too many failed attempts */
        $this->output('This user account is currently locked!', 'Account Locked', 'Error');
        return;
    }
    else
    {
        /* User can be unlocked and form be resubmitted */
        $this->users_model->unlock_user($user_data->user_id);
        $this->submit($post_username, $post_password);
        return FALSE;
    }

    /* User is unlocked from logging in */

    if ($user_data->user_status_id != 2)
    {
        /* User has a status that is not allowed to proceed */
        $this->user_status_message($user_data->user_status_id);
    }

    /* User is registered and validated */

    $regenerated_post_password = $this->genfunc->reGenPassHash($post_password, $user_data->password_hash);

    $failed_logins = $this->session->userdata('failed_logins');

    if ($regenerated_post_password !== $user_data->password)
    {
        /* Password from login from does not match user stored password */

        if ($failed_logins == 0)
        {
            /* First time user has not entered username and password successfully */
            $this->session->set_userdata('failed_logins', 1);
            $this->users_model->increase_login_attempt($this->input->ip_address(), $post_username, gmdate('Y-m-d H:i:s', time()));
            $this->output('Incorrect username and password credentials!', 'Incorrect Login Credentials', 'Error');
            return;
        }

        /* User has atleast one failed login attempt for the current session */

        if ($failed_logins !== 4)
        {
            /* User has a few more chances to get password right */
            $failed_logins++;
            $this->session->set_userdata('failed_logins', $failed_logins);
            $this->users_model->increase_login_attempt($this->input->ip_address(), $post_username, gmdate('Y-m-d H:i:s', time()));
            $this->output('Incorrect username and password credentials!', 'Incorrect Login Credentials', 'Error');
            return;
        }

        $this->users_model->lock_out_user($user_data->user_id, gmdate('Y-m-d H:i:s', time()+(60*15)));
        //$this->functions_model->send_email('maximum_failed_login_attempts_exceeded', $user_data->email_address, $user_data)
        $this->output('Your account is currently locked, we apologize for the inconvienence. You must wait 15 minutes before you can log in again! An email was sent to the owner of this account! Forgotten your username or password? <a href="forgotusername">Forgot Username</a> or <a href="forgotpassword">Forgot Password</a>', 'Account Locked', 'Error');
        return;
    }

    /* Password from login form matches user stored password and user may login */

    $this->output('Successful login! Sending you to the dashboard!', 'Login Sucessful', 'Success');
    return;
}
}



Is This A Good Question/Topic? 0
  • +

Replies To: Flattened Code Has Some Recursion Issue

#2 Atli  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 3719
  • View blog
  • Posts: 5,991
  • Joined: 08-June 10

Re: Flattened Code Has Some Recursion Issue

Posted 31 May 2013 - 01:32 PM

I believe it's related to your user lock code.

If you look at the IF clause that starts on line 139, it calls the is_user_locked method. That method has three potential return values: TRUE if the user is locked, FALSE if the user lock has expired, and NULL (implicitly from lack of a return value) if the user was not locked to begin with. - In that IF clause on line 139 you only do a non-strict Boolean check, meaning that both the FALSE and NULL returns would go on to the ELSE clause while the TRUE return would go to the IF clause.

The ELSE clause does three things: it unlocks the user through the user model, recalls the submit method with the username and password parameters set, and then returns out of the current call of the submit method. The repeated submit call done there goes on to do the user lock check again, and again will inevitably end up in the ELSE clause, which is where your infinite loop happens.

I would suggest reorganizing the lock code so that it either checks for all three potential return values of the is_user_locked method, or that you split that method into two methods: one to check if the user is locked to begin with, and another to check if a locked user can now be unlocked.


Also, aside from that problem. One thing I don't get about the submit method is the input parameters. Regardless of the values passed, lines 111 and 112 will always overwrite them with their respective values from the post method. What was the thinking there? Did you just forget to bypass that if the parameters were set?

This post has been edited by Atli: 31 May 2013 - 01:34 PM

Was This Post Helpful? 2
  • +
  • -

#3 xtremer360  Icon User is offline

  • D.I.C Head

Reputation: -2
  • View blog
  • Posts: 123
  • Joined: 03-March 11

Re: Flattened Code Has Some Recursion Issue

Posted 02 June 2013 - 11:49 AM

Very informative however I'm still confused on adjusting my code.

The last note was I guess still from my unflattened code as I had it in that code and was just trying to move everything over and keep it the same.
Was This Post Helpful? 0
  • +
  • -

#4 Atli  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 3719
  • View blog
  • Posts: 5,991
  • Joined: 08-June 10

Re: Flattened Code Has Some Recursion Issue

Posted 02 June 2013 - 12:25 PM

You need to make sure the if the user was never locked to begin with, that nothing happens. You don't want the code to keep unlocking the use when the user was never locked to begin with. The logic for the user lock thing inside the submit function should read more like this:
IF user lock is in effect:
	IF user lock has not expired:
		Print "user locked" message.
		Return out of the submit function.
	ELSE:
		Remove the user lock through the user model.
		
Process rest of the submit code.


Notice there that in the ELSE clause, the submit function is not re-called as it is in your code. Instead it just unlocks the user and lest the rest of the submit call finish normally. The only case in which the submit code needs to be stopped is if the user lock is still in effect.
Was This Post Helpful? 1
  • +
  • -

#5 xtremer360  Icon User is offline

  • D.I.C Head

Reputation: -2
  • View blog
  • Posts: 123
  • Joined: 03-March 11

Re: Flattened Code Has Some Recursion Issue

Posted 03 June 2013 - 09:04 AM

Does this mean the only thing that needs changed is lines 149-150 of the flattened version? Or am I missing something?
Was This Post Helpful? 0
  • +
  • -

#6 xtremer360  Icon User is offline

  • D.I.C Head

Reputation: -2
  • View blog
  • Posts: 123
  • Joined: 03-March 11

Re: Flattened Code Has Some Recursion Issue

Posted 03 June 2013 - 12:17 PM

I ask this because for some reason every failed attempt I get that its locked out even after I've gone into my db and erased the lock out date.

Here is my updated pastebin.

http://pastebin.com/AWM4etMG

<?php
 
if ( ! defined('BASEPATH')) exit('No direct script access allowed');
 
class Login extends Backend_Controller
{
        public function __construct()
        {
                parent::__construct();
                $this->load->model('users_model');
        }
 
        public function index()
        {
                Asset::js('theme::login.js');
 
                $this->template
                ->title('KOW Manager Login')
                ->set_layout('usermanagement')
                ->build('login');
        }
 
        public function form_is_valid()
        {
                /* Set validation rules for post data */
                $this->form_validation->set_rules('username', 'Username', 'trim|required|xss_clean|min_length[6]|max_length[12]|regex_match[/[a-z0-9]/]');
                $this->form_validation->set_rules('password', 'Password', 'trim|required|xss_clean|min_length[6]|max_length[12]|regex_match[/[a-z0-9]/]');
                //$this->form_validation->set_rules('remember', 'Remember Me', 'trim|xss_clean|integer');
 
                /* Form validation passed */
                return $this->form_validation->run();
        }
 
        public function is_user_locked($user_lock_date)
        {
                if ($user_lock_date !== '0000-00-00 00:00:00')
                {
                        /* User is locked out */
 
                        if (strtotime(gmdate('Y-m-d H:i:s', time())) < strtotime($user_lock_date))
                        {
                                /* User is still locked out */
                                return TRUE;
                        }
                        else
                        {
                                /* User is no longer locked out */
                                return FALSE;
                        }
 
                }
        }
 
        public function check_user_status($user_status_id)
        {
                /* Match user status */
                switch ($user_status_id)
                {
                        case 1:
                                $this->output('Sorry you must verify your account before logging in!', 'Account Unverified', 'Error');
                                break;
                        case 3:
                                $this->output('Your account has been suspended!', 'Account Suspended', 'Error');
                                break;
                        case 4:
                                $this->output('Your account has been suspended!', 'Account Banned', 'Error');
                                break;
                        case 5:
                                $this->output('Your account has been deleted!', 'Account Deleted', 'Error');
                                break;
                        default:
                                return;
                }
        }
 
        public function output($message, $title, $status)
        {
                switch (strtoupper($status))
                {
                        default:
                        case 'ERROR':
                                $status = 'Error';
                                break;
                        case 'NOTICE':
                                $status = 'Notice';
                                break;
                        case 'SUCCESS':
                                $status = 'Success';
                                break;
                        }
                        $this->output
                            ->set_content_type('application/json')
                            ->set_output(json_encode(array('output_status' => $status, 'output_title' => $title, 'output_message' => $message)));
        }
 
        public function start_user_session()
        {
                /* Start session with user id and clear previous failed login attempts */
                $this->session->set_userdata('uid', $user_data->user_id);
                $this->session->unset_userdata('failed_logins');
                $this->users_model->insert_session($user_data->user_id, gmdate('Y-m-d H:i:s', time()));
                return;
        }
 
        public function submit()
        {
                if (!$this->form_is_valid())
                {
                        $this->output('The form did not validate successfully!', 'Form Not Validated', 'Error');
                        return;
                }
 
                /* Post values from login form */
                $post_username = $this->input->post('username');
                $post_password = $this->input->post('password');
 
                /* Test to see value of posted login form */
                //echo '<pre>';
                //var_dump($post_username);
                //var_dump($post_password);
                //echo '</pre>';
                //die();
 
                /* Get user data from post username value */
                $user_data = $this->users_model->get_by('username', $post_username);
 
                /* Test to see value of $user_data */
                //echo '<pre>';
                //var_dump($user_data);
                //echo '</pre>';
                //die();
 
                if (count($user_data) == 0)
                {
                        /* User was not found in database */
                        $this->output('The user was not found in the database!', 'User Not Found', 'Error');
                        return;
                }
 
                /* User was found in database */
 
                if ($this->is_user_locked($user_data->lock_date))
                {
                        /* User is locked from logging in from too many failed attempts */
                        $this->output('This user account is currently locked!', 'Account Locked', 'Error');
                        return;
                }
                else
                {
                        /* User can be unlocked and form be resubmitted */
                        $this->users_model->unlock_user($user_data->user_id);
                }
 
                /* User is unlocked from logging in */
 
                if ($user_data->user_status_id != 2)
                {
                        /* User has a status that is not allowed to proceed */
                        $this->user_status_message($user_data->user_status_id);
                }
 
                /* User is registered and validated */
 
                $regenerated_post_password = $this->genfunc->reGenPassHash($post_password, $user_data->password_hash);
 
                $failed_logins = $this->session->userdata('failed_logins');
 
                if ($regenerated_post_password !== $user_data->password)
                {
                        /* Password from login from does not match user stored password */
 
                        if ($failed_logins == 0)
                        {
                                /* First time user has not entered username and password successfully */
                                $this->session->set_userdata('failed_logins', 1);
                                $this->users_model->increase_login_attempt($this->input->ip_address(), $post_username, gmdate('Y-m-d H:i:s', time()));
                                $this->output('Incorrect username and password credentials!', 'Incorrect Login Credentials', 'Error');
                                return;
                        }
 
                        /* User has atleast one failed login attempt for the current session */
 
                        if ($failed_logins !== 4)
                        {
                                /* User has a few more chances to get password right */
                                $failed_logins++;
                                $this->session->set_userdata('failed_logins', $failed_logins);
                                $this->users_model->increase_login_attempt($this->input->ip_address(), $post_username, gmdate('Y-m-d H:i:s', time()));
                                $this->output('Incorrect username and password credentials!', 'Incorrect Login Credentials', 'Error');
                                return;
                        }
 
                        $this->users_model->lock_out_user($user_data->user_id, gmdate('Y-m-d H:i:s', time()+(60*15)));
                        //$this->functions_model->send_email('maximum_failed_login_attempts_exceeded', $user_data->email_address, $user_data)
                        $this->output('Your account is currently locked, we apologize for the inconvienence. You must wait 15 minutes before you can log in again! An email was sent to the owner of this account! Forgotten your username or password? <a href="forgotusername">Forgot Username</a> or <a href="forgotpassword">Forgot Password</a>', 'Account Locked', 'Error');
                        return;
                }
 
                /* Password from login form matches user stored password and user may login */
 
                $this->output('Successful login! Sending you to the dashboard!', 'Login Sucessful', 'Success');
                return;
        }
}


This post has been edited by Atli: 04 June 2013 - 06:00 AM
Reason for edit:: Please paste your code here, rather than linking to it. Links have a bad habit of dying.

Was This Post Helpful? 0
  • +
  • -

#7 Atli  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 3719
  • View blog
  • Posts: 5,991
  • Joined: 08-June 10

Re: Flattened Code Has Some Recursion Issue

Posted 04 June 2013 - 06:06 AM

There are two things there.

First, you are still not handling the "not locked to begin with" case in your submit method. All you do is check if the user is locked, and if not, then you unlock it. Even if the user was never locked to begin with, your code attempts to unlock it. - This is not likely causing your issue at the moment, but it would still be better to handle that so that user who weren't locked at all aren't unlocked on each submit.

Second is the way you check if a user is locked in your is_user_locked method. You do this:
if ($user_lock_date !== '0000-00-00 00:00:00')


Which means that any case where $user_lock_date isn't precisely 0000-00-00 00:00:00, the system will assume it's locked. That includes values like null, empty strings or booleans. - Have you checked what this value actually is for unlocked users? Are you sure it actually is this value?

Personally I would do a strtotime on that value first, and then check if the returned value is greater than 0. If it is, it has a valid date and should be considered locked.
Was This Post Helpful? 1
  • +
  • -

#8 xtremer360  Icon User is offline

  • D.I.C Head

Reputation: -2
  • View blog
  • Posts: 123
  • Joined: 03-March 11

Re: Flattened Code Has Some Recursion Issue

Posted 04 June 2013 - 11:35 AM

I'm going to work on the first part but I wanted to ask you about the second. I have the default for the user_lock_date set as 0000-00-00 00:00:00 in the database. Which means if its that then the user is obviously not locked out. Is your suggestion still viable.


public function is_user_locked($user_lock_date)
	{
		if (strtotime($user_lock_date) > 0)
		{
			/* User is locked out */

			if (strtotime(gmdate('Y-m-d H:i:s', time())) < strtotime($user_lock_date))
			{
				/* User is still locked out */
				return TRUE;
			}
			else
			{
				/* User is no longer locked out */
				return FALSE;
			}

		}
	}

This post has been edited by xtremer360: 04 June 2013 - 11:38 AM

Was This Post Helpful? 0
  • +
  • -

#9 xtremer360  Icon User is offline

  • D.I.C Head

Reputation: -2
  • View blog
  • Posts: 123
  • Joined: 03-March 11

Re: Flattened Code Has Some Recursion Issue

Posted 04 June 2013 - 12:27 PM

I think after looking at it again I have figured it out.

<?php

if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Login extends Backend_Controller
{
	public function __construct()
	{
		parent::__construct();
		$this->load->model('users_model');
	}

	public function index()
	{
		Asset::js('theme::login.js');

		$this->template
		->title('KOW Manager Login')
		->set_layout('usermanagement')
		->build('login');
	}

	public function form_is_valid()
	{
		/* Set validation rules for post data */
		$this->form_validation->set_rules('username', 'Username', 'trim|required|xss_clean|min_length[6]|max_length[12]|regex_match[/[a-z0-9]/]');
		$this->form_validation->set_rules('password', 'Password', 'trim|required|xss_clean|min_length[6]|max_length[12]|regex_match[/[a-z0-9]/]');
		//$this->form_validation->set_rules('remember', 'Remember Me', 'trim|xss_clean|integer');

		/* Form validation passed */
		return $this->form_validation->run();
	}

	public function is_user_locked($user_lock_date)
	{
		if (strtotime($user_lock_date) > 0)
		{
			/* User is locked out */

			if (strtotime(gmdate('Y-m-d H:i:s', time())) < strtotime($user_lock_date))
			{
				/* User is still locked out */
				return TRUE;
			}
			else
			{
				/* User can be unlocked and form be resubmitted */
				$this->users_model->unlock_user($user_data->user_id);
			
				/* User is no longer locked out */
				return FALSE;
			}

		}
	}

	public function check_user_status($user_status_id)
	{
		/* Match user status */
		switch ($user_status_id)
		{
			case 1:
				$this->output('Sorry you must verify your account before logging in!', 'Account Unverified', 'Error');
				break;
			case 3:
				$this->output('Your account has been suspended!', 'Account Suspended', 'Error');
				break;
			case 4:
				$this->output('Your account has been suspended!', 'Account Banned', 'Error');
				break;
			case 5:
				$this->output('Your account has been deleted!', 'Account Deleted', 'Error');
				break;
			default:
				return;
		}
	}

	public function output($message, $title, $status)
	{
		switch (strtoupper($status))
		{
			default:
			case 'ERROR':
				$status = 'Error';
				break;
			case 'NOTICE':
				$status = 'Notice';
				break;
			case 'SUCCESS':
				$status = 'Success';
				break;
			}
			$this->output
			    ->set_content_type('application/json')
			    ->set_output(json_encode(array('output_status' => $status, 'output_title' => $title, 'output_message' => $message)));
	}

	public function start_user_session()
	{
		/* Start session with user id and clear previous failed login attempts */
		$this->session->set_userdata('uid', $user_data->user_id);
		$this->session->unset_userdata('failed_logins');
		$this->users_model->insert_session($user_data->user_id, gmdate('Y-m-d H:i:s', time()));
		return;
	}

	public function submit()
	{
		if (!$this->form_is_valid())
		{
			$this->output('The form did not validate successfully!', 'Form Not Validated', 'Error');
			return;
		}

		/* Post values from login form */
		$post_username = $this->input->post('username');
		$post_password = $this->input->post('password');

		/* Test to see value of posted login form */
		//echo '<pre>';
		//var_dump($post_username);
		//var_dump($post_password);
		//echo '</pre>';
		//die();

		/* Get user data from post username value */
		$user_data = $this->users_model->get_by('username', $post_username);

		/* Test to see value of $user_data */
		//echo '<pre>';
		//var_dump($user_data);
		//echo '</pre>';
		//die();

		if (count($user_data) == 0)
		{
			/* User was not found in database */
			$this->output('The user was not found in the database!', 'User Not Found', 'Error');
			return;
		}

		/* User was found in database */

		if ($this->is_user_locked($user_data->lock_date))
		{
			/* User is locked from logging in from too many failed attempts */
			$this->output('This user account is currently locked!', 'Account Locked', 'Error');
			return;

		/* User is unlocked from logging in */

		if ($user_data->user_status_id != 2)
		{
			/* User has a status that is not allowed to proceed */
			$this->user_status_message($user_data->user_status_id);
		}

		/* User is registered and validated */

		$regenerated_post_password = $this->genfunc->reGenPassHash($post_password, $user_data->password_hash);

		$failed_logins = $this->session->userdata('failed_logins');

		if ($regenerated_post_password !== $user_data->password)
		{
			/* Password from login from does not match user stored password */

			if ($failed_logins == 0)
			{
				/* First time user has not entered username and password successfully */
				$this->session->set_userdata('failed_logins', 1);
				$this->users_model->increase_login_attempt($this->input->ip_address(), $post_username, gmdate('Y-m-d H:i:s', time()));
				$this->output('Incorrect username and password credentials!', 'Incorrect Login Credentials', 'Error');
				return;
			}

			/* User has atleast one failed login attempt for the current session */

			if ($failed_logins !== 4)
			{
				/* User has a few more chances to get password right */
				$failed_logins++;
				$this->session->set_userdata('failed_logins', $failed_logins);
				$this->users_model->increase_login_attempt($this->input->ip_address(), $post_username, gmdate('Y-m-d H:i:s', time()));
				$this->output('Incorrect username and password credentials!', 'Incorrect Login Credentials', 'Error');
				return;
			}

			$this->users_model->lock_out_user($user_data->user_id, gmdate('Y-m-d H:i:s', time()+(60*15)));
			//$this->functions_model->send_email('maximum_failed_login_attempts_exceeded', $user_data->email_address, $user_data)
			$this->output('Your account is currently locked, we apologize for the inconvienence. You must wait 15 minutes before you can log in again! An email was sent to the owner of this account! Forgotten your username or password? <a href="forgotusername">Forgot Username</a> or <a href="forgotpassword">Forgot Password</a>', 'Account Locked', 'Error');
			return;
		}

		/* Password from login form matches user stored password and user may login */

		$this->output('Successful login! Sending you to the dashboard!', 'Login Sucessful', 'Success');
		return;
	}
}


Was This Post Helpful? 0
  • +
  • -

Page 1 of 1