Code your dreams into reality.
Every line of code is a step towards a better future.
Embrace the bugs, they make you a better debugger.

CodeIgniter 4 Roles and Permissions-Based Access Control Tutorial

Last Updated on September 10, 2024 by

In CodeIgniter 4, Roles and permission means that user can access application as well as features as he gets permission as per the role.

Let’s start to create a roles and permissions based access control system:

Step 1 – CodeIgniter 4 Project

Go to the official website of codeIgniter 4, and download zip and extract it in your xampp or wampp server.

Step 2 – Create Role and Permission Table

Run the following sql queries to create roles, permissions and users table:

CREATE TABLE `roles` (
    `id` INT(11) AUTO_INCREMENT PRIMARY KEY,
    `name` VARCHAR(255) NOT NULL,
    `description` TEXT
);

CREATE TABLE `permissions` (
    `id` INT(11) AUTO_INCREMENT PRIMARY KEY,
    `name` VARCHAR(255) NOT NULL,
    `description` TEXT
);

CREATE TABLE `role_permissions` (
    `role_id` INT(11),
    `permission_id` INT(11),
    FOREIGN KEY (`role_id`) REFERENCES `roles`(`id`),
    FOREIGN KEY (`permission_id`) REFERENCES `permissions`(`id`)
);

CREATE TABLE `users` (
    `id` INT(11) AUTO_INCREMENT PRIMARY KEY,
    `username` VARCHAR(255) NOT NULL,
    `password` VARCHAR(255) NOT NULL,
    `role_id` INT(11),
    FOREIGN KEY (`role_id`) REFERENCES `roles`(`id`)
);

Step 3 – Create Models

Go to the app/models directory and create models named user.php, role.php and permission.php:

Update code in RoleModel.php model file:

<?php namespace App\Models;

use CodeIgniter\Model;

class RoleModel extends Model
{
    protected $table = 'roles';
    protected $primaryKey = 'id';
    protected $allowedFields = ['name', 'description'];
}

Update code in PermissionModel.php model file:

<?php namespace App\Models;

use CodeIgniter\Model;

class PermissionModel extends Model
{
    protected $table = 'permissions';
    protected $primaryKey = 'id';
    protected $allowedFields = ['name', 'description'];
}

Update code in UserModel.php model file:

<?php namespace App\Models;

use CodeIgniter\Model;

class UserModel extends Model
{
    protected $table = 'users';
    protected $primaryKey = 'id';
    protected $allowedFields = ['username', 'password', 'role_id'];

    public function getUserRole($userId)
    {
        return $this->where('id', $userId)->first()['role_id'];
    }
}

Step 4 – Create Controllers

Go to app/controllers directory, and create controllers to manage roles, permissions, and user access.

In RoleController.php file:

<?php namespace App\Controllers;

use App\Models\RoleModel;
use App\Models\PermissionModel;

class RoleController extends BaseController
{
    public function index()
    {
        $model = new RoleModel();
        $data['roles'] = $model->findAll();
        return view('roles/index', $data);
    }

    public function create()
    {
        return view('roles/create');
    }

    public function store()
    {
        $model = new RoleModel();
        $model->save([
            'name' => $this->request->getPost('name'),
            'description' => $this->request->getPost('description'),
        ]);
        return redirect()->to('/roles');
    }
}

In PermissionController.php file:

<?php namespace App\Controllers;

use App\Models\PermissionModel;

class PermissionController extends BaseController
{
    public function index()
    {
        $model = new PermissionModel();
        $data['permissions'] = $model->findAll();
        return view('permissions/index', $data);
    }

    public function create()
    {
        return view('permissions/create');
    }

    public function store()
    {
        $model = new PermissionModel();
        $model->save([
            'name' => $this->request->getPost('name'),
            'description' => $this->request->getPost('description'),
        ]);
        return redirect()->to('/permissions');
    }
}

Step 5 – Implement Role-Based Access Control

Go to App/Libraries directory and create AccessControl.php (Library) file, and implement role based access control logic in it:

<?php namespace App\Libraries;

use App\Models\UserModel;
use App\Models\RoleModel;
use App\Models\PermissionModel;

class AccessControl
{
    protected $userModel;
    protected $roleModel;
    protected $permissionModel;

    public function __construct()
    {
        $this->userModel = new UserModel();
        $this->roleModel = new RoleModel();
        $this->permissionModel = new PermissionModel();
    }

    public function canAccess($userId, $permissionName)
    {
        $roleId = $this->userModel->getUserRole($userId);
        if (!$roleId) {
            return false;
        }

        $permissions = $this->permissionModel->select('permissions.name')
            ->join('role_permissions', 'permissions.id = role_permissions.permission_id')
            ->where('role_permissions.role_id', $roleId)
            ->findColumn('name');

        return in_array($permissionName, $permissions);
    }
}

Step 6 – Use Middleware for Access Control

Create filters in the middleware to enforce user access to application features based on permissions. Edit App/Filters/AccessControlFilter.php file, and add the following code in it:

<?php namespace App\Filters;

use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use CodeIgniter\Filters\FilterInterface;
use App\Libraries\AccessControl;

class AccessControlFilter implements FilterInterface
{
    protected $accessControl;

    public function __construct()
    {
        $this->accessControl = new AccessControl();
    }

    public function before(RequestInterface $request, $arguments = null)
    {
        $userId = session()->get('user_id');
        $requiredPermission = $arguments[0] ?? '';

        if (!$this->accessControl->canAccess($userId, $requiredPermission)) {
            return redirect()->to('/no-access');
        }
    }

    public function after(RequestInterface $request, ResponseInterface $response, $arguments = null)
    {
        // Do something here if needed
    }
}

Step 7 – Set Up Routes and Filters

Edit app/Config/Filters.php file, and add filter in it:

public $aliases = [
    // Other filters...
    'accessControl' => \App\Filters\AccessControlFilter::class,
];

Edit app/Config/Routes.php file, and add routes in it:

$routes->get('/admin', 'AdminController::index', ['filter' => 'accessControl:admin_access']);
$routes->get('/profile', 'UserController::profile', ['filter' => 'accessControl:user_access']);

Step 8 – Create Views

Go to app/views directory and create views file with roles and permissions.

Step 9 – Test the Application

Now setup roles and permissions per user. Assign permissions to users according to roles. And test this application.

Leave a Comment