WebGuard - Advanced PHP Login and User Management

Version 1.3.5


Introduction


WebGuard – Advanced PHP Login and User Management is a PHP application, written on CodeIgniter 4 framework with mysql database, which allows you to better manage your users and permissions. The application is also a useful script for developers who want to save many development hours when creating a framework from scratch.

It was designed to meet all user management needs, control permissions and following good development practices and data security, using framework and components always updated in the latest version.

Requirements

You will need the following sofwares to customize this system.

  1. Code Editing Software (eg: PhpStorm, Visual Studio Code, Sublime Text or Notepad++)
  2. Web Browser for testing (eg: Google Chrome or Mozilla Firefox)
  3. FTP Tool to upload files to Server (eg: FileZilla)
  4. You will need web service with Apache, Nginx or IIS, MySql or MariaDB, Php 7.4 or higher.
  5. Some hosting and cloud tips:

Be careful when editing or customizing source code. If not edited correctly, the source code can break completely and introduce errors.
No support is provided for faulty customization.

How to Install

The installation of the system using the installer is very simple, just follow the step by step below:

  • Step 1 - Copy the SourceCode.zip file to your hosting.
  • Step 2 - Unzip at the root of your hosting.
  • Step 3 - Create a database on your hosting.
  • Step 4 - Go to the website and you will see the installer screen. Similar to the image below.

WebGuard Installer

1- Validation - Check that all statuses are checked, if not, you need to correct to proceed with the installation. Click next to continue installation.

2 - Configuration - In this session, define the database, user and purchase code information in order to proceed.

3 - Finished - Your system has been successfully installed, don't forget to delete the installer folder in "public/install".

How to Install (LocalHost)

For installation on the local machine we recommend using WampServer or Xampp.

How to install on WampServer

  • Step 1 - Download WampServer on your computer.
  • Step 2 - Install and configure WampServer following the video tutorial.
  • Step 3 - To run the system locally you need to configure a VirtualHost following the video tutorial.
  • Step 4 - Now just follow the standard system installation using the system installer.

1 - Download WampServer
https://www.wampserver.com/en/

2 - Install and Configure WampServer

3 - Create VirtualHost in WampServer

4 - System Installer
Click here to see the step by step

How to install on Xampp

  • Step 1 - Download Xampp on your computer.
  • Step 2 - Install and configure Xampp following the video tutorial.
  • Step 3 - To run the system locally you need to configure a VirtualHost following the video tutorial.
  • Step 4 - Now just follow the standard system installation using the system installer.

1 - Download Xampp
https://www.apachefriends.org/

2 - Install and Configure Xampp

3 - Create VirtualHost in Xampp

4 - System Installer
Click here to see the step by step

How to Install (In Folder)

Installing the system within a folder is very simple to configure, just follow the steps below:

  • Step 1 - Copy the SourceCode.zip file to your hosting.
  • Step 2 - Unzip at the root of your hosting.
  • Step 3 - Create a database on your hosting.
  • Step 3 - Open the "Index.php" file in the root of the project.
  • Step 4 - Look for the line "require FCPATH . '/system/app/Config/Paths.php';"
  • Step 5 - Edit with your folder name, example: "require FCPATH . '/my_folder/system/app/Config/Paths.php';"
  • Step 6 - Now just follow the standard installation, click here!
  • Step 7 - After installation, open the "../system/.env" file and edit the "app.baseURL" line with the correct URL and subfolder.

How to Install (CI4 Native)

This is the native version of the project with the standard Codeigniter 4 framework. We recommend using this version only for experienced developers as it does not have an installer like the other version.

Running the local project is very simple, just follow the step by step below:

  • Step 1 - Copy the Native.zip file to your directory.
  • Step 2 - Unzip the zipped file.
  • Step 3 - Create a new MySql database.
  • Step 4 - Open the .env file in the project root and enter the database settings.
  • Step 5 - Open the console in the project folder and run the "php spark migrate" command to create the database structure.
  • Step 6 - Still in the console, run the command "php spark db:seed DataSeeder" to insert data into the database.
  • Step 7 - Still in the console, run the command "php spark serve", the project will be started at the default url "https://localhost:8080".
  • Step 8 - To access, use the default username "admin@admin.com" and the password "12345678"
  • Step 9 - For more information, see the official framework documentation, click here!

How to use the Rest API

We recommend using Postman to test the rest api.

How to install Postman

  • Step 1 - Download Postman on your computer.
  • Step 2 - Install and configure Postman following the video tutorial.
  • Step 3 - Download and import the collection into Postman.

1 - Download Postman
https://www.postman.com/downloads/

2 - Install and Configure Postman

3 - Download API Collection
Open the system and go to the tabs:
General > Api > Download Postman Collection

Below you can configure API usage settings, assign permissions and download the endpoint collection to PostMan.

Below shows how to assign API permissions to user groups.

Check API Status

To check the status of the service, just consult the example below:

Get JWT Token 🔒

How to get JWT token to access blocked methods, just follow the example below:

Authenticate a blocked method 🔓

To authenticate a blocked method, you need to get the JWT token and set it as shown in the example below:

Return XML instead of JSON

Open your ".env" file inside "/system/.env" and change the variable api.return = 'json' to api.return = 'xml'.

How to create a Rest API

To enable the controllers to be public and not pass the login security validation, just follow the steps below:

How to create public controllers

  • Step 1 - Create a controller and a view normally.
  • Step 2 - Open the file in "/system/app/Filters/LoginAuthFilter.php".
  • Step 3 - In the "ignoreListController()" function add the name of your controller.

The example below demonstrates adding a new controller named "Welcome".
Whenever you want to add a controller that will be public, just include it in the list below:

1
2
3
4
5
6
7
8
<?php
    public function ignoreListController(){
        return [
            '',
            'Welcome'
        ];
    }
?>  

If you want to make this new controller the main controller when starting the system, just open the Routes.php file at:
/system/app/config/Routes.php
In the example below, the references to the "Home" controller were commented and the "Welcome" controller was defined as the main controller.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
<?php
namespace Config;
 
// Create a new instance of our RouteCollection class.
$routes = Services::routes();
 
// Load the system's routing file first, so that the app and ENVIRONMENT
// can override as needed.
if (file_exists(SYSTEMPATH . 'Config/Routes.php')) {
    require SYSTEMPATH . 'Config/Routes.php';
}
 
/*
 * --------------------------------------------------------------------
 * Router Setup
 * --------------------------------------------------------------------
 */
$routes->setDefaultNamespace('App\Controllers');
//$routes->setDefaultController('Home');
$routes->setDefaultController('Welcome');
$routes->setDefaultMethod('index');
$routes->setTranslateURIDashes(false);
$routes->set404Override();
$routes->setAutoRoute(true);
 
/*
 * --------------------------------------------------------------------
 * Route Definitions
 * --------------------------------------------------------------------
 */
 
// We get a performance increase by specifying the default
// route since we don't have to scan directories.
 
//WEB ROUTER ------------------------------------------------------
//------------------------------------------------------------------
//$routes->get('/', 'Home::index');
$routes->get('/', 'Welcome::index');
$routes->get('lang/{locale}', 'Language::index');
 
//API ROUTER ------------------------------------------------------
//------------------------------------------------------------------
$routes->get('api/','Api::index');
$routes->get('api/status','Api::status');
$routes->post('api/signIn','Api::signIn');
 
//API ROUTER USER ------------------------------------------------------
//------------------------------------------------------------------
$routes->get('api/user/','Api::user/all');
$routes->get('api/user/(:segment)','Api::user/id/$1');
$routes->post('api/user/','Api::user/add');
$routes->put('api/user/(:segment)','Api::user/edit/$1');
$routes->delete('api/user/(:segment)','Api::user/delete/$1');
 
 
/*
 * --------------------------------------------------------------------
 * Additional Routing
 * --------------------------------------------------------------------
 *
 * There will often be times that you need additional routing and you
 * need it to be able to override any defaults in this file. Environment
 * based routes is one such time. require() additional route files here
 * to make that happen.
 *
 * You will have access to the $routes object within that file without
 * needing to reload it.
 */
if (file_exists(APPPATH . 'Config/' . ENVIRONMENT . '/Routes.php')) {
    require APPPATH . 'Config/' . ENVIRONMENT . '/Routes.php';
}
?>  

How to create a CRUD

To enable the controllers to be public and not pass the login security validation, just follow the steps below:

How to create public controllers

  • Step 1 - Create a table in the database.
  • Step 2 - Create a model.
  • Step 3 - Create a controller.
  • Step 4 - Create a view.

Let's create a general to-do list example.

1 - Create a table in the database

Inside the mysql database add your table eg:

1
2
3
4
5
6
7
8
CREATE TABLE `task` (
    `id_task` int(11) NOT NULL AUTO_INCREMENT,
    `title` varchar(150) COLLATE latin1_general_ci NOT NULL,
    `description` text COLLATE latin1_general_ci NOT NULL,
    `created_at` timestamp NOT NULL,
    `updated_at` timestamp NOT NULL ON UPDATE CURRENT_TIMESTAMP,
    PRIMARY KEY (`id_task`)
  ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;                                 

2 - Create a model

Inside the Models folder create the TaskModel.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
namespace App\Models;
 
class TaskModel extends BaseModel
{
    protected $table = 'task';
    protected $primaryKey = 'id_task';
    protected $allowedFields = [
        'title',
        'description'
    ];
    protected $useTimestamps = true;
    protected $createdField  = 'created_at';
    protected $updatedField  = 'updated_at';
}
?>  

3 - Create a controller

Inside the Controllers folder create the Task.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
<?php
namespace App\Controllers;
 
use App\Models\TaskModel;
 
class Task extends BaseController
{
    private $task_model;
 
    function __construct()
    {
        $this->task_model = new TaskModel();
    }
 
    public function index()
    {
        $data['title'] = [
            'module' => 'Task List',
            'page'   => 'All Tasks',
            'icon'  => 'fas fa-tasks'
        ];
 
        $data['breadcrumb'] = [
            ['title' => 'Dashboard', 'route' => "/home", 'active' => false],
            ['title' => 'Task List', 'route'  => "", 'active' => true]
        ];
 
        $data['btn_add'] = [
            'title' => 'Add New Task',
            'route'   => '/task/add',
            'class'   => 'btn btn-lg btn-primary float-md-right',
            'icon'  => 'fas fa-plus'
        ];
 
        $table = new \CodeIgniter\View\Table([
            'table_open' => '<table id="table-grid" class="table">'
        ]);
 
        $table->setHeading('Title','Created at');
 
        $data['grid'] = $this->task_model->select('title, created_at, id_task AS options')
            ->orderBy('created_at','DESC')
            ->findAll();
 
        foreach ($data['grid'] as $key => $value){
            $id = $data['grid'][$key]['options'];
            $data['grid'][$key]['options'] = ''.
                '<div class="btn-group mr-1 mb-1" xmlns="http://www.w3.org/1999/html">
                    <button type="button" class="btn btn-primary btn-block dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                        Options
                    </button>
                    <div class="dropdown-menu">
                        <a class="dropdown-item" href="/task/edit/'.$id.'"><i class="fas fa-edit"></i> Edit</a>
                        <button class="dropdown-item" onclick="delete_task(\''.$id.'\');"><i class="fas fa-trash"></i> Delete</button>
                    </div>
                    </div>
                ';
        }
 
        $data['table'] = $table;
 
        echo view(getenv('theme.path').'main/header');
        echo view(getenv('theme.path').'form/task/index',$data);
        echo view(getenv('theme.path').'main/footer');
    }
 
    public function add()
    {
        helper('form');
 
        $data['title'] = [
            'module' => 'Add Task',
            'page'   => 'Add Task',
            'icon'  => 'far fa-plus-square'
        ];
 
        $data['breadcrumb'] = [
            ['title' => 'Dashboard', 'route' => "/home", 'active' => false],
            ['title' => 'List Task', 'route' => "/task", 'active' => false],
            ['title' => 'Add Task', 'route'  => "", 'active' => true]
        ];
 
        $data['btn_return'] = [
            'title' => 'Come Back',
            'route'   => '/task',
            'class'   => 'btn btn-dark mr-1',
            'icon'  => 'fas fa-angle-left'
        ];
 
        $data['btn_submit'] = [
            'title' => 'Save',
            'route'   => '',
            'class'   => 'btn btn-primary mr-1',
            'icon'  => 'fas fa-save'
        ];
 
        echo view(getenv('theme.path').'main/header');
        echo view(getenv('theme.path').'form/task/form',$data);
        echo view(getenv('theme.path').'main/footer');
    }
 
    public function edit($token=null)
    {
        if(empty($token)){
            return redirect()->to('/task');
        }
 
        helper('form');
 
        $data['title'] = [
            'module' => 'Edit Task',
            'page'   => 'Edit Task',
            'icon'  => 'fas fa-edit'
        ];
 
        $data['breadcrumb'] = [
            ['title' => 'Dashboard', 'route' => "/home", 'active' => false],
            ['title' => 'List Task', 'route' => "/task", 'active' => false],
            ['title' => 'Edit Task', 'route'  => "", 'active' => true]
        ];
 
        $data['btn_return'] = [
            'title' => 'Come Back',
            'route'   => '/task',
            'class'   => 'btn btn-dark mr-1',
            'icon'  => 'fas fa-angle-left'
        ];
 
        $data['btn_submit'] = [
            'title' => 'Save',
            'route'   => '',
            'class'   => 'btn btn-primary mr-1',
            'icon'  => 'fas fa-save'
        ];
 
        $data['obj'] = $this->task_model->where('id_task', $token)->first();
        if($data['obj']==null){
            return redirect()->to('/task');
        }
 
        echo view(getenv('theme.path').'main/header');
        echo view(getenv('theme.path').'form/task/form',$data);
        echo view(getenv('theme.path').'main/footer');
    }
 
    public function store()
    {
        $session = session();
        helper('form');
 
        $rules = [
            'title'        => 'required',
            'description'  => 'required'
        ];
 
        $rules_error = [
            'title' => [
                'required' => 'Title field is required.',
            ],
            'description' => [
                'required' => 'Description field is required',
            ]
        ];
 
        if ($this->validate($rules,$rules_error)){
            if(empty($this->request->getPost('id_task'))){
                $this->task_model->save([
                    'id_task' => null,
                    'title' => $this->request->getPost('title'),
                    'description' => $this->request->getPost('description')
                ]);
                $session->setFlashdata('sweet', ['success','Added successfully!']);
                return redirect()->to('/task');
            }else{
                $this->task_model->save([
                    'id_task' => $this->request->getPost('id_task'),
                    'title' => $this->request->getPost('title'),
                    'description' => $this->request->getPost('description')
                ]);
                $session->setFlashdata('sweet', ['success','Successfully edited!']);
                return redirect()->to('/task');
            }
        }else{
            $session->setFlashdata('error','error');
            $this->add();
        }
    }
 
    public function delete($id)
    {
        $session = session();
        if(!empty($session->get('token'))){
            $this->task_model->where('id_task', $id)->delete();
            $session->setFlashdata('sweet', ['success','Successfully deleted!']);
            return redirect()->to('/task');
        }else{
            return redirect()->to('/login');
        }
    }
}
?>  

4 - Create a view

Inside the Views/themes/focus2/form/ folder create the "task" folder and inside it create two index.php and form.php files

index.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
<!--Content Body-->
<div class="content-body">
    <div class="container-fluid">
        <div class="row page-titles mx-0">
            <div class="col-sm-6 p-md-0">
                <div class="welcome-text">
                    <h4><i class="<?= $title['icon']??'' ?>"></i> <?= $title['module']??'' ?></h4>
                    <span class="ml-1"><?= $title['page']??'' ?></span>
                </div>
            </div>
            <div class="col-sm-6 p-md-0 justify-content-sm-end mt-2 mt-sm-0 d-flex">
                <ol class="breadcrumb">
                    <?php foreach ($breadcrumb??[] as $item) : ?>
                        <?php if (!$item['active']) : ?>
                            <li class="breadcrumb-item"><a href="<?= $item['route'] ?>"><?= $item['title'] ?></a></li>
                        <?php else : ?>
                            <li class="breadcrumb-item active"><?= $item['title'] ?></li>
                        <?php endif; ?>
                    <?php endforeach; ?>
                </ol>
            </div>
        </div>
 
        <div class="row">
            <div class="col-12">
                <div class="card">
                    <div class="card-header row">
                        <div class="col-sm-6">
                            <h4 class="card-title"><?= $title['page']??'' ?></h4>
                        </div>
                        <div class="col-sm-6 justify-content-sm-end mt-2 mt-sm-0 d-flex">
                            <a href="<?= $btn_add['route']??'#'?>" class="<?= $btn_add['class']??''?>">
                                <i class="<?= $btn_add['icon']??'' ?>"></i> <?= $btn_add['title']??'' ?>
                            </a>
                        </div>
                    </div>
                    <div class="card-body">
                        <div class="table-responsive">
                            <?php
                            use CodeIgniter\View\Table;
                            $table = $table??new Table();
                            echo $table->generate($grid??[]);
                            ?>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
<!-- Required vendors -->
<script src="/themes/focus2/vendor/global/global.min.js"></script>
<script src="/themes/focus2/js/quixnav-init.js"></script>
<script src="/themes/focus2/js/custom.min.js"></script>
<!-- Datatable -->
<script src="/themes/focus2/vendor/datatables/js/jquery.dataTables.min.js"></script>
<script src="/themes/focus2/vendor/pickers/daterange/moment.min.js"></script>
<script src="/themes/focus2/vendor/datatables/js/dataTables.datetime.js"></script>
<script src="/themes/focus2/vendor/datatables/js/dataTables.buttons.min.js"></script>
<script src="/themes/focus2/vendor/datatables/js/buttons.bootstrap4.min.js"></script>
<script src="/themes/focus2/vendor/datatables/js/jszip.min.js"></script>
<script src="/themes/focus2/vendor/datatables/js/pdfmake.min.js"></script>
<script src="/themes/focus2/vendor/datatables/js/vfs_fonts.js"></script>
<script src="/themes/focus2/vendor/datatables/js/buttons.html5.min.js"></script>
<script src="/themes/focus2/vendor/datatables/js/buttons.print.min.js"></script>
<script src="/themes/focus2/vendor/datatables/js/buttons.colVis.min.js"></script>
<!-- Alert -->
<script src="/themes/focus2/vendor/sweetalert2/dist/sweetalert2.min.js"></script>
<script src="/themes/focus2/vendor/toastr/js/toastr.min.js"></script>
<!-- Custom -->
<script src="/assets/js/main.js"></script>
<script>
    $(document).ready(function () {
        "use strict";
        let data = [
            {
                targets: 1,
                render: $.fn.dataTable.render.moment('YYYY-MM-DD HH:mm:ss','<?=momentDateTimeJS()?>')
            }
        ];
        let order = [[0, "asc"]];
        let translate = '/themes/focus2/vendor/datatables/locales/<?=langJS()?>.json';
        let button = ["<?=lang("App.global_copy")?>","<?=lang("App.global_print")?>","<?=lang("App.global_excel")?>","<?=lang("App.global_pdf")?>"];
        loadDataTable('table-grid', '', translate, true, true, order, data, button);
    });
    function delete_task(id){
        "use strict";
        swal({
            title: "Are you sure you want to delete?",
            text: "You will not be able to retrieve this information!",
            type: "warning",
            showCancelButton: !0,
            confirmButtonColor: "#f34141",
            confirmButtonText: "Yes, Delete!",
            cancelButtonText: "Cancel",
            closeOnConfirm: !1
        }).then(function(isConfirm) {
            console.log(isConfirm);
            if (isConfirm.value) {
                window.location.href = '/task/delete/'+id;
            }
        })
    }
</script>
<?= sweetAlert() ?>
form.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
<!--Content Body-->
<div class="content-body">
    <div class="container-fluid">
        <div class="row page-titles mx-0">
            <div class="col-sm-6 p-md-0">
                <div class="welcome-text">
                    <h4><i class="<?= $title['icon']??'' ?>"></i> <?= $title['module']??'' ?></h4>
                    <span class="ml-1"><?= $title['page']??'' ?></span>
                </div>
            </div>
            <div class="col-sm-6 p-md-0 justify-content-sm-end mt-2 mt-sm-0 d-flex">
                <ol class="breadcrumb">
                    <?php foreach ($breadcrumb??[] as $item) : ?>
                        <?php if (!$item['active']) : ?>
                            <li class="breadcrumb-item"><a href="<?= $item['route'] ?>"><?= $item['title'] ?></a></li>
                        <?php else : ?>
                            <li class="breadcrumb-item active"><?= $item['title'] ?></li>
                        <?php endif; ?>
                    <?php endforeach; ?>
                </ol>
            </div>
        </div>
        <div class="row">
            <div class="col-12">
                <div class="card">
                    <div class="card-header">
                        <h4 class="card-title"><?= $title['page']??'' ?></h4>
                    </div>
                    <div class="card-body">
                        <?= formAlert() ?>
                        <form class="form" action="/task/store" method="post">
                            <?= csrf_field() ?>
                            <input type="hidden" name="id_task" value="<?= (isset($obj)) ? $obj['id_task'] : set_value('id_task') ?>">
                            <div class="form-body">
                                <div class="row">
                                    <div class="col-md-12">
                                        <div class="form-group">
                                            <label for="title" class="text-dark">Title</label>
                                            <input type="text" name="title" id="title" class="form-control" value="<?= (isset($obj)) ? $obj['title'] : set_value('title') ?>">
                                        </div>
                                    </div>
                                    <div class="col-md-12">
                                        <div class="form-group">
                                            <label class="text-dark">Description</label>
                                            <textarea class="form-control" id="description" name="description" rows="3"><?= (isset($obj)) ? $obj['description'] : set_value('description') ?></textarea>
                                        </div>
                                    </div>
                                </div>
                            </div>
                            <div class="form-actions mt-2">
                                <a href="<?= $btn_return['route']??'#' ?>" class="<?= $btn_return['class']??''?>">
                                    <i class="<?= $btn_return['icon']??'' ?>"></i> <?= $btn_return['title']??'' ?>
                                </a>
                                <button type="submit" class="<?= $btn_submit['class']??''?>">
                                    <i class="<?= $btn_submit['icon']??'' ?>"></i> <?= $btn_submit['title']??'' ?>
                                </button>
                            </div>
                        </form>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
<!-- Required vendors -->
<script src="/themes/focus2/vendor/global/global.min.js"></script>
<script src="/themes/focus2/js/quixnav-init.js"></script>
<script src="/themes/focus2/js/custom.min.js"></script>
<script src="/themes/focus2/vendor/select2/js/select2.full.min.js"></script>
<!-- Form -->
<script>
    $(document).ready(function () {
        "use strict";
        $('#title').focus();
    });
</script>

How to create a new language

To enable the controllers to be public and not pass the login security validation, just follow the steps below:

Create a new language

  • Step 1 - Duplicate the "en" folder within languages "/system/app/Language".
  • Step 2 - Change the folder name to your language abbreviation.
  • Step 3 - Modify the text inside the App.php and Validation.php files.
  • Step 4 - Open the "App.php" file in "/system/app/Config/App.php".
  • Step 5 - Modify line 100 by adding your new acronym to the array.
  • Step 6 - Open the "App.php" file in "/system/app/Views/themes/focus2/main/header.php".
  • Step 7 - Add a new link in the nav-item dropdown of the language menu eg:
1
2
3
4
<a href="<?= site_url('lang/en'); ?>" class="dropdown-item">
<img src="/assets/flags/us_32_circle.png">
<span class="ml-2"><?= lang("App.lang_en") ?></span>
</a>                               

How to Create Add-on

Below you will learn how to create and install an add-on.

How to create an add-on

There is an add-on called "Tasks", it is a basis on how to create an add-on, you can use it as a basis to create yours.

Add-ons in Codeigniter 4 follow the same folder pattern as the main application.
Your add-on information is added to the app.json file.
Create table, insert, update or delete are added to SQL files.

Below shows how to configure app.json

How to install an add-on

Open the modules and upload the .zip file for the addon you want to use.

After loading, it will display a success message and list the new add-on.

To view the addon in the menu, you need to assign access permission to the addon, as shown below:

Assign the groups that can have access to this addon.

After assigning the permissions correctly, simply save and update the page that will display the addon menus in the system menu.

How to Activate 2FA

Access the settings and activate as shown in the image below:

After activating the settings, each user must access their profile and activate the 2FA function as shown in the image below:

After activating, the user must save the backup keys and the secret key.
Remembering that you must scan the QRCode with the Google Authenticator application or another similar application to be able to generate dynamic OTP codes.

Google Authenticator

Download from Play Store
Download from App Store

How to Activate oAuth

Below shows how to assign information to each provider and the return url in the system.

WebGuard uses the "HybridAuth" library to assign several providers, if you want to add more providers or see the documentation, just click here.

Codeigniter 4 Course (Free)

Codeigniter 4 complete course

Open full course on YouTube

Framework Documentation

CodeIgniter 4

CodeIgniter is a PHP application development framework.
Currently the system uses version 4.4.3

CodeIgniter4 User Guide CodeIgniter4 GitHub

Support Desk

If you need assistance please contact us so we can help you in the best way, thanks!

Project RoadMap

Roadmap next version

1
2
3
4
5
6
7
8
9
10
11
-----------------------------------------------------------------------------------------
Version 1.4.0
-----------------------------------------------------------------------------------------
- CodeIgniter Update
- CRUD Generator.
- Page Generator
- IP Manager.
- Session Manager.
- God mode.
- Create dynamic dashboards.
- Uploading new layouts to the backend.

Project Updates (Changelog)

Changelog

1
2
3
4
5
6
7
8
9
10
11
12
13
14
-----------------------------------------------------------------------------------------
Version 1.3.5 - 12 November 2023
-----------------------------------------------------------------------------------------
- CodeIgniter v4.4.3.
- Fixed Add-on Permissions.
- Focus2 Dark Theme (Backend).
- Adjustment in PT and ES Translation.
- Adjustment in the user menu.
- Adjustment in the frontend menu.
- Added RTL Support (Backend)
- Added Arabic language.
- Adjusted when deleting account from profile.
- Adjusted confirmation email tag.
- Documentation has been improved and updated.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
-----------------------------------------------------------------------------------------
Version 1.3.0 - 08 July 2023
-----------------------------------------------------------------------------------------
- CodeIgniter v4.3.6.
- Created the Frontend page.
- Enable and Disable Frontend.
- Pusher notification.
- Add rules in the API.
- International Telephone Input.
- GDPR Cookies, Data and Deletion.
- Allow the API to select more than one permission group.
- Creation of Modules.
- Access permissions on modules.
- Allow to disable the use of modules.
- Using HMVC with WebGuard.
- Other minor improvements.
1
2
3
4
5
6
7
8
9
10
-----------------------------------------------------------------------------------------
Version 1.2.1 - 28 June 2022
-----------------------------------------------------------------------------------------
- Fixed responsive in table grids.
- Fixed Side-Menu and button transparency reported by Diego.
- Fixed the "oAuth Authentication" screen the responsive part.
- Updated CSS and JS from Focus2 template.
- CodeIgniter v4.2.1
- Composer Updated all components.
- Field Country and User Language and Edited Profile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
-----------------------------------------------------------------------------------------
Version 1.2.0 - 29 April 2022
-----------------------------------------------------------------------------------------
- Added DataGrid pagination through the database in data blocks.
- Added description of the permissions group in the users list.
- Added email sending test in settings.
- Fixes of "use strict" in DataGrid.
- Fixes in notifications and alerts.
- Fixes in sending e-mail.
- Fixes in user profile update.
- Fixes when deleting user allows to delete their activities together.
- Fixes in recaptcha and hcaptcha.
- Updated all composer components.
- Framework update for CodeIgniter v4.1.9.
- Among other Fixes.
1
2
3
4
5
6
-----------------------------------------------------------------------------------------
Version 1.1.0 - 04 February 2022
-----------------------------------------------------------------------------------------
- Documentation Update.
- PHP 8.X.X support.
- Framework Update for CodeIgniter v4.1.8.
1
2
3
4
-----------------------------------------------------------------------------------------
Version 1.0.0 - 16 January 2022
-----------------------------------------------------------------------------------------
- Initial Release.