Skip to content

Commit 03c8145

Browse files
committed
Add support for middlewares
1 parent 88fbda2 commit 03c8145

File tree

10 files changed

+224
-4
lines changed

10 files changed

+224
-4
lines changed

README.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,19 @@ If you loves CodeIgniter 3 & Vue.js, you must try this one to make your life eas
2424

2525
I try to keep this project as simple as possible, so you can making a changes to suit your needs. No need to install a bunch of libraries for making something simple.
2626

27-
### Restful API support: response helper, ajax request validation ✅
27+
### Restful API support: response helper, ajax request validation ✅
2828
- application/config/routes.php
2929
- application/core/MY_Controller.php
3030
- application/controllers/api/*
3131

3232
### Middlewares
33-
- Not implemented yet!
33+
- application/core/MY_Controller.php
34+
- application/middlewares/*
35+
- application/helpers/auth_helper.php
36+
- application/config/config.php
37+
- application/config/routes.php
38+
- application/config/autoload.php
39+
- application/controllers/api/v1/Auth.php
40+
- application/controllers/api/v1/User.php
3441

3542
Powered by [ngekoding.github.io](https://ngekoding.github.io)

application/config/autoload.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
|
5959
| $autoload['libraries'] = array('user_agent' => 'ua');
6060
*/
61-
$autoload['libraries'] = array();
61+
$autoload['libraries'] = array('session');
6262

6363
/*
6464
| -------------------------------------------------------------------

application/config/config.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,7 @@
380380
$config['sess_driver'] = 'files';
381381
$config['sess_cookie_name'] = 'ci_session';
382382
$config['sess_expiration'] = 7200;
383-
$config['sess_save_path'] = NULL;
383+
$config['sess_save_path'] = sys_get_temp_dir();
384384
$config['sess_match_ip'] = FALSE;
385385
$config['sess_time_to_update'] = 300;
386386
$config['sess_regenerate_destroy'] = FALSE;

application/config/routes.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,4 +65,5 @@
6565
*/
6666
$route['api/v1/users']['GET'] = 'api/v1/user';
6767
$route['api/v1/users/(:num)']['GET'] = 'api/v1/user/show/$1';
68+
$route['api/v1/test-login/(:any)']['POST'] = 'api/v1/auth/test_login/$1';
6869
$route['api/(.*)'] = '404';
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
defined('BASEPATH') OR exit('No direct script access allowed');
3+
4+
class Auth extends MY_Controller {
5+
6+
public function __construct()
7+
{
8+
parent::__construct();
9+
10+
$this->load->helper('auth');
11+
}
12+
13+
public function test_login($role)
14+
{
15+
/**
16+
* Make userdata object as you want
17+
* For this example, we need a role that will used
18+
* for role middleware
19+
*/
20+
$userdata = (object) [
21+
'id' => 1,
22+
'name' => 'Nur Muhammad',
23+
'role' => $role
24+
];
25+
26+
set_userdata($userdata);
27+
28+
return send_response([
29+
'success' => TRUE,
30+
'data' => $userdata
31+
]);
32+
}
33+
}

application/controllers/api/v1/User.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,29 @@ class User extends MY_Controller {
66
// All method must called by ajax request
77
protected $ajax_request_only = TRUE;
88

9+
/**
10+
* Limit method access with middlewares
11+
* For this example:
12+
* - index can only accessed by authenticated user (whatever it's role)
13+
* - show can only accessed by authenticated user with role 'admin'
14+
*
15+
* You can use auth controller to make a login test with spesific role
16+
* example.com/index.php/api/v1/auth/test-login/admin
17+
*/
18+
protected $middlewares = [
19+
['name' => 'auth'],
20+
[
21+
'name' => 'role',
22+
'behavior' => [
23+
'type' => 'only',
24+
'methods' => ['show']
25+
],
26+
'extras' => [
27+
'roles' => ['admin']
28+
]
29+
]
30+
];
31+
932
// Just example data
1033
// In the real case, this data from the DB
1134
private $users = [

application/core/MY_Controller.php

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,28 @@ class MY_Controller extends CI_Controller {
1111
*/
1212
protected $ajax_request_only = FALSE;
1313

14+
/**
15+
* Middlewares to manage access
16+
*
17+
* Formatted as an array that contains these keys:
18+
* - name Middleware name (required)
19+
* - behavior An array of validation behavior. (optional)
20+
* Format: ['type' => except or only, 'methods' => [...]]
21+
* If empty or not defined, will applied to all methods
22+
* except: applied to all methods except the given
23+
* only: applied only to the given methods
24+
* - extras Extra paramaters to passing to the run method. (optional)
25+
*/
26+
protected $middlewares = [];
27+
1428
public function __construct()
1529
{
1630
parent::__construct();
1731

1832
$this->load->helper('api');
1933

2034
$this->ajax_request_validator();
35+
$this->run_middlewares();
2136
}
2237

2338
/**
@@ -48,4 +63,53 @@ private function ajax_request_validator()
4863

4964
if ($error) send_bad_request('Ajax request only!');
5065
}
66+
67+
/**
68+
* Run middlewares validation
69+
*/
70+
private function run_middlewares()
71+
{
72+
foreach ($this->middlewares as $middleware) {
73+
$name = $middleware['name'];
74+
$behavior = isset($middleware['behavior'])
75+
? $middleware['behavior']
76+
: NULL;
77+
$extras = isset($middleware['extras'])
78+
? $middleware['extras']
79+
: [];
80+
81+
$run = TRUE;
82+
if (!empty($behavior)) {
83+
$type = $behavior['type'];
84+
$methods = $behavior['methods'];
85+
86+
// Get current requested method
87+
$requested_method = $this->router->fetch_method();
88+
89+
if ($type == 'except' && in_array($requested_method, $methods)) {
90+
$run = FALSE;
91+
} elseif ($type == 'only' && !in_array($requested_method, $methods)) {
92+
$run = FALSE;
93+
}
94+
}
95+
96+
if ($run) {
97+
$class_name = ucfirst(strtolower($name)) . '_middleware';
98+
$file_name = $class_name . '.php';
99+
$file_path = APPPATH . 'middlewares/' . $file_name;
100+
if (file_exists($file_path)) {
101+
require $file_path;
102+
$ci =& get_instance();
103+
$obj = new $class_name($ci, $this, $extras);
104+
$obj->run();
105+
} else {
106+
if (ENVIRONMENT == 'development') {
107+
throw new Exception('Unable to find middleware: ' . $file_name);
108+
} else {
109+
throw new Exception('Sorry something went wrong.');
110+
}
111+
}
112+
}
113+
}
114+
}
51115
}

application/helpers/auth_helper.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
define('AUTH_SESS_NAME', 'app_logged_in');
4+
5+
function set_userdata($data) {
6+
$_ci =& get_instance();
7+
$_ci->session->set_userdata(AUTH_SESS_NAME, $data);
8+
}
9+
10+
function userdata() {
11+
$_ci =& get_instance();
12+
13+
$userdata = $_ci->session->userdata(AUTH_SESS_NAME);
14+
15+
return $userdata;
16+
}
17+
18+
function clear_userdata() {
19+
$_ci =& get_instance();
20+
$_ci->session->unset_userdata(AUTH_SESS_NAME);
21+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
class Auth_middleware {
4+
5+
private $ci;
6+
private $controller;
7+
private $extras;
8+
9+
/**
10+
* Accepting codeigniter instance, current controller & extras
11+
*/
12+
public function __construct($ci, $controller, ...$extras)
13+
{
14+
$this->ci = $ci;
15+
$this->controller = $controller;
16+
$this->extras = $extras;
17+
}
18+
19+
public function run()
20+
{
21+
$this->ci->load->helper([
22+
'api',
23+
'auth'
24+
]);
25+
26+
if (empty(userdata())) {
27+
return send_response([
28+
'success' => FALSE,
29+
'error' => 'Login required!'
30+
], HTTP_UNAUTHORIZED);
31+
}
32+
}
33+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php
2+
3+
class Role_middleware {
4+
5+
private $ci;
6+
private $controller;
7+
private $extras;
8+
9+
/**
10+
* Accepting codeigniter instance & controller
11+
*/
12+
public function __construct($ci, $controller, $extras)
13+
{
14+
$this->ci = $ci;
15+
$this->controller = $controller;
16+
$this->extras = $extras;
17+
}
18+
19+
public function run()
20+
{
21+
$this->ci->load->helper([
22+
'api',
23+
'auth'
24+
]);
25+
26+
$allowed_roles = $this->extras['roles'];
27+
28+
$userdata = userdata();
29+
$role = $userdata->role ?? NULL;
30+
31+
if (!in_array($role, $allowed_roles)) {
32+
return send_response([
33+
'success' => FALSE,
34+
'error' => 'Sorry, you don\'t have access to this resource.'
35+
], HTTP_FORBIDDEN);
36+
}
37+
}
38+
}

0 commit comments

Comments
 (0)