0

I am attempting to do an if statement to populate the correct navigation menu for different levels of permission users.

I have a class called users, which has the following function called 'hasPermission':

public function hasPermission($key) {
    $group = $this->_db->get('groups', array('id', '=', $this->data()->group));

    if($group->count()) {
        $permissions = json_decode($group->first()->permissions, true);

        if($permissions[$key] == true) {
            return true;
        }
    }
    return false;
}

Which works off the following groups in my database:

enter image description here

Then in a different file, I am trying to get the current user's signed in permission with $permission (I think the error is in here) and then use the if statement to populate the correct file.

$permission = $user->hasPermission($group);

if($permission == 'User') {
    include 'nav/userNav.php';
} else if ($permission == 'Admin') {
    include 'nav/adminNav.php';
}

Does anyone see what I am doing wrong?

EDIT:

User class full code:

<?php
class User {
    private $_db,
            $_data,
            $_sessionName,
            $_cookieName,
            $_isLoggedIn;

    public function __construct($user = null) {
        $this->_db = DB::getInstance();

        $this->_sessionName = Config::get('session/session_name');
        $this->_cookieName = Config::get('remember/cookie_name');

        if(!$user) {
            if(Session::exists($this->_sessionName)) {
                $user = Session::get($this->_sessionName);

                if($this->find($user)) {
                    $this->_isLoggedIn = true;
                } else {
                    // process Logout
                }
            }
        } else {
            $this->find($user);
        }
    }

    public function update($fields = array(), $id = null) {

        if(!$id && $this->isLoggedIn()) {
            $id = $this->data()->id;
        }

        if(!$this->_db->update('users', $id, $fields)) {
            throw new Exception('There was a problem updating!');
        }
    }

    public function create($fields = array()) {


        if(!$this->_db->insert('users', $fields)) {
            throw new Exception('There was a problem creating an account:' .  $this->_db->errorMessage());

        }
    $this->lastId = $this->_db->lastInsertId();
    }

    public function find($user = null) {
        if($user) {
            $field = (is_numeric($user)) ? 'id' : 'username';
            $data = $this->_db->get('users', array($field, '=', $user));

            if($data->count()) {
                $this->_data = $data->first();
                return true;
            }
        }
        return false;
    }

    public function login($username = null, $password = null, $remember = false) {

        if(!$username && !$password && $this->exists()) {
            Session::put($this->_sessionName, $this->data()->id);
        } else {
            $user = $this->find($username);

            if($user) {
                if($this->data()->password === Hash::make($password, $this->data()->salt)) {
                //if(Auth::check($this->data()->password, $password)){
                    Session::put($this->_sessionName, $this->data()->id);

                    if($remember) {
                        $hash = Hash::unique();
                        $hashCheck = $this->_db->get('users_session', array('user_id', '=', $this->data()->id));

                        if(!$hashCheck->count()) {
                            $this->_db->insert('users_session', array(
                                'user_id' => $this->data()->id,
                                'hash' => $hash
                            ));
                        } else {
                            $hash = $hashCheck->first()->hash;
                        }

                        Cookie::put($this->_cookieName, $hash, Config::get('remember/cookie_expiry'));
                    }
                    return true;
                }
            }

        }
        return false;
    }

    public function hasPermission($key) {
        $group = $this->_db->get('groups', array('id', '=', $this->data()->group));

        if($group->count()) {
            $permissions = json_decode($group->first()->permissions, true);

            if($permissions[$key] == true) {
                return true;
            }
        }
        return false;
    }

    public function exists() {
        return (!empty($this->_data)) ? true : false;
    }

    public function logout() {

        $this->_db->delete('users_session', array('user_id', '=', $this->data()->id));

        Session::delete($this->_sessionName);
        Cookie::delete($this->_cookieName);
    }

    public function data() {
        return $this->_data;
    }
    public function isLoggedIn() {
        return $this->_isLoggedIn;
    }
}
?>

EDIT #2 - Trying to create a new function for this:

public function getGroup($groupkey) {
    $group_name = $this->_db->get('groups', array('name'));
}

Then in the other file where I am trying to call this:

$permission = $user->getGroup($group_name);

if($permission == 'User') {
    include 'nav/userNav.php';
} else if ($permission == 'Admin') {
    include 'nav/adminNav.php';
}

Edit #3

With this code:

 public function getGroup($groupkey) {
    $group_name = $this->_db->get('groups', array('name'));
    return $group_name;
}

I get this erorr:

Fatal error: Uncaught ArgumentCountError: Too few arguments to function User::getGroup(), 0 passed in /home/house/public_html/admin/index.php on line 322 and exactly 1 expected in /home/house/public_html/classes/User.php:116 Stack trace: #0 /home/house/public_html/admin/index.php(322): User->getGroup() #1 {main} thrown in

Action function in DB class.

public function action($action, $table, $where = array()){
    if(count($where) === 3){
        $operators = array('=', '>', '<', '>=', '<=');

        $field      = $where[0];
        $operator   = $where[1];
        $value      = $where[2];

        if(in_array($operator, $operators)) {
            $sql = "{$action} FROM {$table} WHERE {$field} {$operator} ?";
            $date = new DateTime();
            file_put_contents('debug_log', "\n[{$date->format('Y-m-d H:i:s')}] $sql", FILE_APPEND);

            $results = $this->query($sql, array($value));
                file_put_contents('debug_log1', "\n[{$date->format('Y-m-d H:i:s')}] $sql" . print_r($results, 1), FILE_APPEND);
            return $this;

        }
    }
    return false;
}

EDIT - FULL DB CLASS

<?php
class DB {
    private static $_instance = null;
    private $_pdo,
            $_query, 
            $_error = false,
            $_results,
            $_count = 0,
            $_errmsg = "";

    private function __construct(){
        try {
            $this->_pdo = new PDO('mysql:host=' . Config::get('mysql/host') . ';dbname=' . Config::get('mysql/db'), Config::get('mysql/username'), Config::get('mysql/password'));
            /*$host = config::get('mysql/host');
            $database = config::get('mysql/db');
            $username = config::get('mysql/user');
            $password = config::get('mysql/password');

            $dbh = new PDO('mysql:host='.$host.';dbname='.$database.', $username, $password);*/
            } catch(PDOException $e) {
        die($e->getMEssage());
        }   
    }
    //**********LastID

    public function lastInsertId () { 
        return $this->_pdo->lastInsertId(); 
    } 
    public static function getInstance() {
        if(!isset(self::$_instance)) {
            self::$_instance = new DB();
        }
        return self::$_instance;
    }
    public function query($sql, $params = array()){
"DEBUG DB::query called<br>SQL: $sql<br><br>PARAMS: " . implode("<br>", $params) . "<hr>\n";        
        $this->_error = false;
        if($this->_query = $this->_pdo->prepare($sql)) {
"DEBUG: prepared statement created ok<hr>\n";           
            $x = 1;
            if(count($params)){
                foreach($params as $param){
                    $this->_query->bindValue($x, $param);
                    $x++;
                }
            }
            if($this->_query->execute()){
                $this->_results = $this->_query->fetchALL(PDO::FETCH_OBJ);
                $this->_count = $this->_query->rowCount();
"DEBUG: query succeeded, rowcount was: " . $this->_count . "<hr>\n";                
            } else {
    "DEBUG: query failed to execute, reason:<br>" . implode( "<br>", $this->_query->errorInfo() ) . "<hr>\n";   
                $this->_error = true;
            }
        } else {
"DEBUG: Failed to create prepared statement<hr>\n";
        }   
        return $this;
    }
    public function action($action, $table, $where = array()){
        if(count($where) === 3){
            $operators = array('=', '>', '<', '>=', '<=');

            $field      = $where[0];
            $operator   = $where[1];
            $value      = $where[2];

            if(in_array($operator, $operators)) {
                $sql = "{$action} FROM {$table} WHERE {$field} {$operator} ?";
                $date = new DateTime();
                file_put_contents('debug_log', "\n[{$date->format('Y-m-d H:i:s')}] $sql", FILE_APPEND);

                $results = $this->query($sql, array($value));
                    file_put_contents('debug_log1', "\n[{$date->format('Y-m-d H:i:s')}] $sql" . print_r($results, 1), FILE_APPEND);
                return $this;

            }
        }
        return false;
    }
    public function get($table, $where){
        return $this->action('SELECT *', $table, $where);
    }
    public function delete($table, $where){
        return $this->action('DELETE', $table, $where);
    }
    public function insert($table, $fields = array()) {
        $keys = array_keys($fields);
        $values = '';
        $x = 1;

        foreach($fields as $field) {
            $values .= '?';
            if($x < count($fields)) {
                $values .= ', ';
            }
            $x++;
        }

        $sql = "INSERT INTO {$table} (`" . implode('`, `', $keys) . "`) Values ({$values})";

        return ! $this-> query($sql, $fields)->error(); 
    }
    public function update($table, $id, $fields) {
        $set = '';
        $x = 1;

        foreach($fields as $name => $value) {
            $set .= "{$name} = ?";
            if($x < count($fields)) {
                $set .= ', ';
            }
            $x++;
        }

        $sql = "UPDATE {$table} SET {$set} WHERE id = {$id}";

        return ! $this-> query($sql, $fields)->error();
    }
    public function results() {
        return $this->_results;
    }
    public function first() {
        return $this->results()[0];
    }
    public function error() {
        return $this->_error;
    }
    public function errorMessage() { 
        return $this->_errmsg; 
    }
    public function count(){
        return $this->_count;
    }
}
?>
Paul
  • 3,348
  • 5
  • 32
  • 76
  • Why do you store the permissions as a JSON object? – Script47 Mar 25 '19 at 17:14
  • `$permission = 'User'` is assigning the value `$permission == 'User'` would mean check if equal to. – Nigel Ren Mar 25 '19 at 17:15
  • 1
    You're returning `true` or `false` but then check to see if it is `User` or `Admin` which it will never be. – AbraCadaver Mar 25 '19 at 17:19
  • Add a new method called `getGroup()` (or something similar) and implement it there. Don't try to do it under `hasPermission`; that should only return a boolean. – waterloomatt Mar 25 '19 at 17:41
  • @waterloomatt Thanks for the tip. I just tried it, but still getting the undefined variable for `$group_name` in the file calling this. I edited my question (see EDIT #2) with how I tried to do this. – Paul Mar 25 '19 at 17:53
  • Really hard for someone to help you with this because we don't know what your DB query returns. Is it an array, an object, a string, ...? That being said, I see a few larger issues. Function `getGroup` needs to `return` something. Secondly, in theory, you shouldn't have to pass anything to `getGroup` because it should look up the role name based on the logged in user, which I assume you store in `$this->data()->group`. – waterloomatt Mar 25 '19 at 18:01
  • @waterloomatt Here is the function for `get` which I was trying to use for this and so does the function `hasPermission` ........ `public function get($table, $where){ return $this->action('SELECT *', $table, $where); }` – Paul Mar 25 '19 at 18:07
  • @waterloomatt I just added an EDIT #3 to my question with new code and the error it shows. – Paul Mar 25 '19 at 18:12
  • `Too few arguments to function` because you defined the function with 1 argument and are passing 0 arguments. Remove the $argument from the function definition. Also, you haven't implemented the function. You need to retrieve the role (or all roles depending on your requirements) based on the currently logged in user. – waterloomatt Mar 25 '19 at 18:24
  • @waterloomatt Sorry, you are losing me. I am pretty new to creating functions like this. – Paul Mar 25 '19 at 18:28
  • @waterloomatt Alright, I removed the argument and the error went away. I am just not sure how to retrieve the rolls. – Paul Mar 25 '19 at 18:37
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/190696/discussion-between-waterloomatt-and-paul). – waterloomatt Mar 26 '19 at 12:19
  • @waterloomatt The chat site it blocked through my work. I just asked for it to be unblocked. I will let you know when it has been done. – Paul Mar 26 '19 at 12:23
  • OK - in the meantime, can you please post the full contents of your DB class - unless it is hundreds of lines long. Also, can you confirm that a user can only have 1 role or is it 1 to many? – waterloomatt Mar 26 '19 at 12:26
  • 1
    @waterloomatt DB class added. The user can only have one role. – Paul Mar 26 '19 at 12:32

2 Answers2

1

Based on the updated information, I can see that you're using PDO and executing fetchALL and returning results as an array of stdClass objects (FETCH_OBJ). Not sure why you're storing permission at all, let alone as a JSON object but thankfully, we don't need that column in this case. We can simply look up name based on id.

It is important to realize that $this->_db->get(... returns an instance of your DB class (or false) so you should name your variable appropriately, $db. Let me know if you run into any issues and I'll try to help out.

<?php 
/**
 * Returns the role name of the currently logged in user. If no role can be
 * determined, an empty string will be returned.
 * @return string
 */
public function getGroup() 
{
    $role = '';
    // I really can't tell what `$this->data()->group` is but 
    // I'm making the assumption that it is the logged in user's role ID. 
    $db = $this->_db->get('groups', array('id', '=', $this->data()->group));

    if($db->count() > 0) { 
        // `first()` returns the first element of the results as a stdClass object.
        // https://www.geeksforgeeks.org/what-is-stdclass-in-php/
        $role = $db->first()->name;
    }   

    return $role;  
}
waterloomatt
  • 3,662
  • 1
  • 19
  • 25
0
...
public function hasPermission($key) {
    $group = $this->_db->get('groups', array('id', '=', $this->data()->group));

    if($group->count()) {
        $permissions = json_decode($group->first()->permissions, true);

        if($permissions[$key] == true) {
            return $key;//change true here to the role
        }
    }
    return false;
}
...
auwalup
  • 93
  • 8