Redirect user to different page based on role in database Slim 3, Twig & Eloquent


#1

I’m making trouble redirecting users to the right page upon logging in. What I mean by this is if a user in the database has a role of admin then he should be redirected to admin.twig (But it could just as well be a HTML or PHP file I’m just using twig) or if there a customer they should be sent to customer.twig and so on…

Lets say I have the following users in my database:

 id name email           password  role
 
 1  Sam  Johndoe@gmail.com pass123   0

 2  John Johndoe@gmail.com pass123   2

Let’s say, admin = 0, customer = 1 and client = 2

So in the example above John would be an admin and Sam would be a Client

Here is my file structure

   ├── Slim-3-app
     ├── app
       ├── Auth
           Auth.php
       ├── Controllers
         |──Auth
            AuthController.php
       ├── Middleware
       ├── Models
             User.php
       ├── Validation
       ├── routes.php
     ├── bootstrap
         app.php
     ├── resources
       ├── views
         home.twig
         admin.twig
         client.twig
         csutomer.twig    

Routes.php:

$app->get('/', 'HomeController:index')->setName('home');
$app->get('/admin', 'AdminController:adminControllerFunction')->setName('admin');
$app->get('/customer', 'CustomerController:customerControllerFunction')->setName('customer');
$app->get('/client', 'ClientController:clientControllerFunction')->setName('client');

User.php:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
	protected $fillable = [
		'name',
		'email',
		'password',
		'role'
	];

	public function setPassword($password)
	{
		$this->update([
			'password' => password_hash($password, PASSWORD_DEFAULT)
		]);
	}
}

Auth.php:

<?php

namespace App\Auth;

use App\Models\User;

class Auth
{
	public function user()
	{
		if (isset($_SESSION['user'])) {
			return User::find($_SESSION['user']);
		}
	}

	public function check()
	{
		if (isset($_SESSION['user'])) {
			return isset($_SESSION['user']);
		}
	}

	public function checkRole($role)
	{
		$role = User::where('role' , $role)->first();

	}


	public function attempt($email, $password)
	{
		// get the data of the attempted user
		$user = User::where('email' , $email)->first();


		// check if the user exists
		if (!$user) {
			return false;
		}


		// check if password is valid
		if (password_verify($password, $user->password)) {
			$_SESSION['user'] = $user->id;
			return true;
		}

		return false;
	}

	public function logout()
	{
		unset($_SESSION['user']);
	}
}

AuthController.php:

<?php

namespace App\Controllers\Auth;

use App\Models\User;
use App\Controllers\Controller;
use Respect\Validation\Validator as v;
class AuthController extends Controller
{
	public function getSignOut($request, $response)
	{
		$this->auth->logout();
		// flash message
		$this->flash->addMessage('error', 'You have been signed out');
		return $response->withRedirect($this->router->pathFor('home'));
	}
	// signin controller
	public function getSignIn($request, $response)
	{
		return $this->view->render($response, 'auth/signin.twig');
	}

	public function postSignIn($request, $response)
	{
		// use the attempt class
		$auth = $this->auth->attempt(
			$request->getParam('email'),
			$request->getParam('password'),
			$request->getParam('role')
		);

		if (!$auth) {
			// flash message
			$this->flash->addMessage('error', 'Could not sign you in with those details');

			return $response->withRedirect($this->router->pathFor('auth.signin'));
		}

		// flash message
		$this->flash->addMessage('success', 'Successfully signed in');
		return $response->withRedirect($this->router->pathFor('home'));

		// if(checkrole() = 0 ){
		// 	$this->flash->addMessage('success', 'Admin Successfully signed in');
		// 	return $response->withRedirect($this->router->pathFor('home'));
		// } else {
		// 	$this->flash->addMessage('success', 'Admin Successfully signed in');
		// 	return $response->withRedirect($this->router->pathFor('home'));
		// }
		// This does not work but I need something like this
	}

	// signup controller
	public function getSignUp($request, $response)
	{
		return $this->view->render($response, 'auth/signup.twig');
	}

	public function postSignUp($request, $response)
	{

		$validation = $this->validator->validate($request, [
			'email' => v::noWhitespace()->notEmpty()->emailAvailable(),
			'name' => v::notEmpty()->alpha(),
			'password' => v::noWhitespace()->notEmpty(),
		]);

		if ($validation->failed()) {
			return $response->withRedirect($this->router->pathFor('auth.signup'));
		}

		$user = User::create([
			'email' => $request->getParam('email'),
			'name' => $request->getParam('name'),
			'password' => password_hash($request->getParam('password'), PASSWORD_DEFAULT),
			'role' => $request->getParam('role'),
		]);

		// flash a message
		$this->flash->addMessage('info', 'You have been signed up');

		// log the user directly in
		$this->auth->attempt($user->email, $request->getParam('password'));

		return $response->withRedirect($this->router->pathFor('home'));
	}
}

app.php

<?php

use Respect\Validation\Validator as v;

<?php

use Respect\Validation\Validator as v;

session_start();

require __DIR__ . '/../vendor/autoload.php';

$app = new \Slim\App([
	'settings' => [
		'displayErrorDetails' => true,
		'db' => [
			'driver' 	=> 'mysql',
			'host' 		=> 'localhost',
			'database' 	=> 'eshop',
			'username' 	=> 'root',
			'password' 	=> '',
			'charset' 	=> 'utf8',
			'collation'	=> 'utf8_unicode_ci',
			'prefix'	=> '',
		]
	],

]);

$container = $app->getContainer();

// setup illuminate (Model generator)
$capsule = new Illuminate\Database\Capsule\Manager;
$capsule->addConnection($container['settings']['db']);
$capsule->setAsGlobal();
$capsule->bootEloquent();

$container['validator'] = function ($container) {
	return new App\Validation\Validator;
};

// add Illuminate package
$container['db'] = function ($container) use ($capsule){
	return $capsule;
};

// add Auth class
$container['auth'] = function($container){
	return new \App\Auth\Auth;
};

// add Slim Flash messages
$container['flash'] = function () {
    return new \Slim\Flash\Messages();
};

// add views to the application
$container['view'] = function($container){
	$view = new \Slim\Views\Twig(__DIR__ . '/../resources/views', [
		'cache' => false,
	]);

	$view->addExtension(new Slim\Views\TwigExtension(
		$container->router,
		$container->request->getUri()
	));

	// let the view have access to auth controller
	$view->getEnvironment()->addGlobal('auth', [
		'check' => $container->auth->check(),
		'user' => $container->auth->user()
	]);

	// let the view have access to flash messages
	$view->getEnvironment()->addGlobal('flash', $container->flash);

	return $view;
};

$container['HomeController'] = function($container){
	return new \App\Controllers\HomeController($container);
};


$container['AdminController'] = function($container){
	return new \App\Controllers\AdminController($container);
};

$container['CustomerController'] = function($container){
	return new \App\Controllers\CustomerController($container);
};

$container['ClientController'] = function($container){
	return new \App\Controllers\ClientController($container);
};

$container['AuthController'] = function($container){
	return new \App\Controllers\Auth\AuthController($container);
};


$container['PasswordController'] = function($container){
	return new \App\Controllers\Auth\PasswordController($container);
};

// add Slim CSRF
$container['csrf'] = function($container){
	return new \Slim\Csrf\Guard;
};

// give back errors
$app->add(new \App\Middelware\ValidationErrorsMiddelware($container));

// give back the old input
$app->add(new \App\Middelware\OldInputMiddelware($container));

// give back a csrf generated key
$app->add(new \App\Middelware\CsrfViewMiddelware($container));

// run the crsf check
$app->add($container->csrf);

// setup custom rules
v::with('App\\Validation\\Rules\\');

require  __DIR__ . '/../app/routes.php';

I’ve tried to check the role in the Authcontroller and then redirect to the desired route using and if statement(its commented out above^) but that unfortunately does not work.


#2

Can you post what AuthController.php looks like when you think it should work, but it is not? There are a few reasons why simply uncommenting those lines wouldn’t work, for example you’re returning a response before the role is checked, so you wouldn’t get that far. And even if you did get to that check both conditions are redirecting to the same place. So it would be helpful to see the actual code that isn’t working.