Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

PHP PHP User Authentication Setting up Authorization System User Admin Panel

User Admin Panel PHP - Can someone please assist

The following are not showing on the site:

1) My Account 2) Logout

Hence I cannot access as an Administrator

In addition: 1) Add and Delete send to Login 2) Only Edit works

Code for: nav.php is as follows:

<nav class="navbar navbar-default navbar-static-top">
    <div class="container">

        <div class="navbar-header">
            <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
                <span class="sr-only">Toggle navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand" href="/">Book Voting</a>
        </div>


        <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
            <ul class="nav navbar-nav">
                <li><a href="/">Home</a></li>
                <li><a href="/books.php">Book List</a></li>
                <li><a href="/add.php">Add Book</a></li>
            </ul>
            <ul class="nav navbar-nav navbar-right">
                <?php if (!isAuthenticated()) : ?>
                <li><a href="/login.php">Login</a></li>
                <li><a href="/register.php">Register</a></li>
                <?php else: ?>
                <li><a href="/account.php">My Account</a></li>
                <li><a href="/admin.php">Admin</a></li>
                <li><a href="/procedures/doLogout.php">Logout</a></li>
                <?php endif; ?>
            </ul>
        </div>
    </div>
</nav>

CODE for functions.php is as follows:

<?php 

/**
 * @return \Symfony\Component\HttpFoundation\Request
 */
function request() {
    return \Symfony\Component\HttpFoundation\Request::createFromGlobals();
}

function addBook($title, $description) {
    global $db;
    $ownerId = 0;

    try {
        $query = "INSERT INTO books (name, description, owner_id) VALUES (:name, :description, :ownerId)";
        $stmt = $db->prepare($query);
        $stmt->bindParam(':name', $title);
        $stmt->bindParam(':description', $description);
        $stmt->bindParam(':ownerId', $ownerId);
        return $stmt->execute();
    } catch (\Exception $e) {
        throw $e;
    }
}

function updateBook($bookId, $title, $description) {
    global $db;

    try {
        $query = "UPDATE books SET name=:name, description=:description WHERE id=:bookId";
        $stmt = $db->prepare($query);
        $stmt->bindParam(':name', $title);
        $stmt->bindParam(':description', $description);
        $stmt->bindParam(':bookId', $bookId);
        return $stmt->execute();
    } catch (\Exception $e) {
        throw $e;
    }
}

function getAllBooks() {
    global $db;

    try {
        $query = "SELECT books.*, sum(votes.value) as score "
            . " FROM books "
            . " LEFT JOIN votes ON (books.id = votes.book_id) "
            . " GROUP BY books.id "
            . " ORDER BY score DESC";
        $stmt = $db->prepare($query);
        $stmt->execute();
        return $stmt->fetchAll();
    } catch (\Exception $e) {
        throw $e;
    }
}

function getBook($id) {
    global $db;

    try {
        $query = "SELECT * FROM books WHERE id = ?";
        $stmt = $db->prepare($query);
        $stmt->bindParam(1, $id);
        $stmt->execute();
        return $stmt->fetch(PDO::FETCH_ASSOC);
    } catch (\Exception $e) {
        throw $e;
    }
}

function vote($bookId, $score) {
    global $db;
    $userId = 0;

    try {
        $query = 'INSERT INTO votes (book_id, user_id, value) VALUES (:bookId, :userId, :score)';
        $stmt = $db->prepare($query);
        $stmt->bindParam(':bookId', $bookId);
        $stmt->bindParam(':userId', $userId);
        $stmt->bindParam(':score', $score);
        $stmt->execute();
    } catch (\Exception $e) {
        die('Something happened with voting. Please try again');
    }
}

function redirect($path, $extra = []) {
    $response = \Symfony\Component\HttpFoundation\Response::create(null, \Symfony\Component\HttpFoundation\Response::HTTP_FOUND, ['Location' => $path]);
    if (key_exists('cookies', $extra)) {
        foreach ($extra['cookies'] as $cookie) {
            $response->headers->setCookie($cookie);
        }
    }
    $response->send();
    exit;
}

function getAllUsers() {
    global $db;

    try {
        $query = "SELECT * FROM users";
        $stmt = $db->prepare($query);
        $stmt->execute();
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    } catch (\Exception $e) {
        throw $e;
    }
}

function findUserByEmail($email) {
    global $db;

    try {
        $query = "SELECT * FROM users WHERE email = :email";
        $stmt = $db->prepare($query);
        $stmt->bindParam(':email', $email);
        $stmt->execute();
        return $stmt->fetch(PDO::FETCH_ASSOC);

    } catch (\Exception $e) {
        throw $e;
    }
}

function findUserByAccessToken() {
    global $db;

    try {
        $userId = decodeJwt('sub');
    } catch (\Exception $e) {
        throw $e;
    }

    try {
        $query = "SELECT * FROM users WHERE id = :userId";
        $stmt = $db->prepare($query);
        $stmt->bindParam(':userId', $userId);
        $stmt->execute();
        return $stmt->fetch(PDO::FETCH_ASSOC);

    } catch (\Exception $e) {
        throw $e;
    }
}

function createUser($email, $password) {
    global $db;

    try {
        $query = "INSERT INTO users (email, password, role_id) VALUES (:email, :password, 2)";
        $stmt = $db->prepare($query);
        $stmt->bindParam(':email', $email);
        $stmt->bindParam(':password', $password);
        $stmt->execute();
        return findUserByEmail($email);
    } catch (\Exception $e) {
        throw $e;
    }
}

function updatePassword($password, $userId) {
    global $db;

    try {
        $query = 'UPDATE users SET password=:password WHERE id = :userId';
        $stmt = $db->prepare($query);
        $stmt->bindParam(':password', $password);
        $stmt->bindParam(':userId', $UserId);
        $stmt->execute();
    } catch (\Exception $e) {
        return false;
    }

    return true;
}

function promote($userId) {
    global $db;

    try {
        $query = "UPDATE users SET role_id=1 WHERE id = ?";
        $stmt = $db->prepare($query);
        $stmt->bindParam(1,$userId);
        $stmt->execute();
    } catch (\Exception $e) {
        throw $e;
    }
}

function demote($userId) {
    global $db;

    try {
        $query = "UPDATE users SET role_id=2 WHERE id = ?";
        $stmt = $db->prepare($query);
        $stmt->bindParam(1,$userId);
        $stmt->execute();
    } catch (\Exception $e) {
        throw $e;
    }
}

function decodeJwt($prop = null) {
    \Firebase\JWT\JWT::$leeway = 1;
    $jwt = \Firebase\JWT\JWT::decode(
        request()->cookies->get('access_token'),
        getenv('SECRET_KEY'),
        ['HS256']
    );

    if ($prop === null) {
        return $jwt;
    }

    return $jwt->{$prop};
}

function isAuthenticated() {
    if (!request()->cookies->has('access_token')) {
        return false;
    }

    try {
        decodeJwt();
        return true;
    } catch (\Exception $e) {
        return false;
    }
}

function requireAuth() {
    if(!isAuthenticated()) {
        $accessToken = new \Symfony\Component\HttpFoundation\Cookie("access_token", "Expired", time()-3600, '/', getenv('COOKIE_DOMAIN'));
        redirect('/login.php', ['cookies' => [$accessToken]]);
    }
}

function requireAdmin() {
    if(!isAuthenticated()) {
        $accessToken = new \Symfony\Component\HttpFoundation\Cookie("access_token", "Expired", time()-3600, '/', getenv('COOKIE_DOMAIN'));
        redirect('/login.php', ['cookies' => [$accessToken]]);
    }

    try {
        if (! decodeJwt('is_admin')) {
            $session->getFlashBag()->add('error', 'Not Authorized');
            redirect('/');
        }
    } catch (\Exception $e) {
        $accessToken = new \Symfony\Component\HttpFoundation\Cookie("access_token", "Expired", time()-3600, '/', getenv('COOKIE_DOMAIN'));
        redirect('/login.php', ['cookies' => [$accessToken]]);
    }
}

function isAdmin() {
    if (!isAuthenticated()) {
        return false;
    }

    try {
        $isAdmin = decodeJwt('is_admin');
    } catch (\Exception $e) {
        return false;
    }

    return (boolean)$isAdmin;
}

function isOwner($ownerId) {
    if (!isAuthenticated()) {
        return false;
    }

    try {
        $userId = decodeJwt('sub');
    } catch (\Exception $e) {
        return false;
    }

    return $ownerId == $userId;
}

function display_errors() {
    global $session;

    if (!$session->getFlashBag()->has('error')) {
        return;
    }

    $messages = $session->getFlashBag()->get('error');

    $response = '<div class="alert alert-danger alert-dismissable">';
    foreach ($messages as $message) {
        $response .= "{$message}<br />";
    }
    $response .= '</div>';

    return $response;
}
function display_success() {
    global $session;

    if(!$session->getFlashBag()->has('success')) {
        return;
    }

    $messages = $session->getFlashBag()->get('success');

    $response = '<div class="alert alert-success alert-dismissable">';
    foreach($messages as $message ) {
        $response .= "{$message}<br>";
    }
    $response .= '</div>';

    return $response;
}

CODE for index.php is as follows:

<?php
require_once __DIR__ . '/inc/bootstrap.php';
require_once __DIR__ . '/inc/head.php';
require_once __DIR__ . '/inc/nav.php';
?>
<div class="container">
    <div class="well">
        <h2>Book Voting System</h2>
        <?php echo display_errors(); ?>
        <?php echo display_success(); ?>
        <p>Welcome to the book voting system.  Use this system to submit books you like and see if others like them as well
        by letting them upvote it.</p>
    </div>
</div>
<?php
require_once __DIR__ . '/inc/footer.php';

3 Answers

Alena Holligan
STAFF
Alena Holligan
Treehouse Teacher

Try removing the ending slash from the COOKIE_DOMAIN

COOKIE_DOMAIN=port-80-s76xvamq9b.treehouse-app.com
Alena Holligan
STAFF
Alena Holligan
Treehouse Teacher

Hi tinashegondokondo

My first suggestion is that you may not actually be logged in. Did you test out the login and make sure you could read your access token?

On index.php

if (request()->cookies->has('access_token')) {
    echo "logged in";
} else {
    echo "not logged in";
}

If the cookie isn't working properly, one of the most common reasons is that the COOKIE_DOMAIN in the .env file is not set properly. When using workspaces it should be set to something like

COOKIE_DOMAIN=port-80-m1m8flu0vu.treehouse-app.com

If this doesn't work, please share your code. Either as a "snapshot" (top right hand corner) from Workspaces or post to GitHub.

Hi Alena, Please find the "snapshot"

https://w.trhou.se/e1k3tvmtcw

I send an email and tried to post to GitHub but I am not sure if I was doing the correct thing.

Regards

Tinashe

Steve Meadows
seal-mask
.a{fill-rule:evenodd;}techdegree
Steve Meadows
Full Stack JavaScript Techdegree Student 15,218 Points

Hi,

I am not sure if this will help as it solved my issue on a live web server which i was having the same problem as you..

you have:- $dotenv = new Dotenv\Dotenv(DIR);

in your bootstrap folder which in mine kept displaying an error.. i changed it to $dotenv = new Dotenv(DIR);

and this seemed to help and solve my problem

Hope this helps