Commit 72891cb7 by nurchamim

memindahkan luthier ke third party

parent 4dfa9586
......@@ -17,4 +17,5 @@ $hook['post_controller_constructor'] = array(
'filename' => 'LanguageLoader.php',
'filepath' => 'hooks'
);
require_once APPPATH."third_party/luthier/vendor/autoload.php";
$hook = Luthier\Hook::getHooks();
......@@ -49,6 +49,8 @@ defined('BASEPATH') OR exit('No direct script access allowed');
| Examples: my-controller/index -> my_controller/index
| my-controller/my-method -> my_controller/my_method
*/
require_once APPPATH."third_party/luthier/vendor/autoload.php";
$route = Luthier\Route::getRoutes();
$route['default_controller'] = 'Auth';
......
vendor/*
/docs/en/manifest.json
/docs/es/manifest.json
.buildpath
.project
.settings/org.eclipse.wst.validation.prefs
MIT License
Copyright (c) 2018 Ingenia Software
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
{
"name" : "luthier/luthier",
"type" : "library",
"description": "Improved routing, middleware support, authentication tools and more for CodeIgniter 3 framework",
"license" : "MIT",
"homepage" : "https://luthier.ingenia.me/ci/en/",
"authors": [
{
"name" : "Anderson Salas",
"email" : "anderson@ingenia.me",
"homepage": "https://ingenia.me",
"role" : "Lead developer"
}
],
"keywords": [
"codeigniter", "routing", "middleware", "luthier"
],
"minimum-stability": "stable",
"require": {
"php" : ">=5.6.0",
"maximebf/debugbar": "~1.0"
},
"require-dev": {
"phpunit/phpunit": "7"
},
"support": {
"email": "anderson@ingenia.me"
},
"autoload": {
"psr-4": {
"Luthier\\": "src/"
}
}
}
[//]: # ([author] Anderson Salas, translated by Julio Cedeño)
[//]: # ([meta_description] Read the official documentation of Luthier CI and discover the possibilities it offers, see examples, use cases and much more)
# Welcome
### About Luthier CI
**Luthier CI** is a plugin for CodeIgniter that adds interesting features, designed to made easy the construction of large websites and APIs in general. It was made to integrate as best as possible with the framework, so everything that already exists in your application should continue to work without problems after installing Luthier CI.
This documentation assumes that you have basic knowledge about CodeIgniter. If you have never used CodeIgniter, a good starting point is their [official documentation](https://www.codeigniter.com/user_guide)
Luthier CI is free software and is available under a MIT license.
### Features
#### Improved routing
Luthier CI replaces the way you define routes in your application by a syntax inspired by Laravel.
For example, instead of defining a big array of routes similar to this:
```php
$route['catalog/cars/(:any)']['GET'] = 'CarsController/catalog/$1';
$route['catalog/cars/(:any)/(:any)']['GET'] = 'CarsController/catalog/$1/$2';
$route['catalog/bikes/(:any)']['GET'] = 'BikesController/catalog/$1';
$route['catalog/bikes/(:any)']['POST'] = 'BikesController/catalog/$1';
$route['catalog/bikes/(:any)/(:any)']['GET'] = 'BikesController/catalog/$1/$2';
$route['catalog/bikes/(:any)/(:any)']['POST'] = 'BikesController/catalog/$1/$2';
$route['catalog/airplanes/(:any)']['GET'] = 'AirplanesController/catalog/$1/$2';
$route['catalog/airplanes/(:any)/(:any)']['GET'] = 'AirplanesController/catalog/$1/$2';
```
... you can write it in a more compact way:
```php
Route::group('catalog', function(){
Route::get('cars/{category_id}/{filter_by?}', 'CarsController@catalog');
Route::match(['get','post'], 'bikes/{category_id}/{filter_by?}', 'BikesController@catalog');
Route::get('airplanes/{category_id}/{filter_by?}', 'AirplanesController@catalog');
});
```
In addition, Luthier CI helps you to keep your routes organized, since each type of route has it's own file where it must be defined: there is one file for HTTP routes, another for AJAX routes and another for CLI routes.
#### Middleware
Luthier CI introduces the concept of _Middleware_ in the framework.
Used correctly, the middleware can help you create filters and actions on your controllers that, otherwise, would be very tedious to implement using _libraries_ and _helpers_.
You can use the middleware both in specific routes and in groups of routes, or even globally in your application.
#### Easy installation
Luthier CI is installed through Composer and uses CodeIgniter _hooks_ to integrate into your application. Forget about copying or moving files or following huge lists of steps to get Luthier CI working. In most cases the installation takes no more than 5 minutes!
### Community and support
To report errors and propose changes please visit the [Luthier CI repository on Github](https://github.com/ingeniasoftware/luthier-ci)
\ No newline at end of file
[//]: # ([author] Anderson Salas, translated by Julio Cedeño)
[//]: # ([meta_description] Learn how to get Luthier CI and install it in your CodeIgniter application with step-by-step instructions, it takes no more than 5 minutes!)
# Installation
### Contents
1. [Requirements](#requirements)
2. [Installation](#installation)
1. [Get Luthier CI](#get-luthier-ci)
2. [Enable Composer autoload and hooks](#enable-composer-autoload-and-hooks)
3. [Connect Luthier CI with your application](#connect-luthier-ci-with-your-application)
3. [Initialization](#initialization)
### <a name="requirements"></a> Requirements
* PHP >= 5.6 (Compatible con PHP 7)
* CodeIgniter 3
### <a name="installation"></a> Installation
#### <a name="get-luthier-ci"></a> Get Luthier CI
<div class="alert alert-info">
<i class="fa fa-info-circle" aria-hidden="true"></i>
<strong>Composer required</strong>
<br />
Luthier CI is installed through Composer. You can get it <a href="https://getcomposer.org/download/">here</a>.
</div>
Go to the `application` folder and execute the following command:
```bash
composer require luthier/luthier
```
#### <a name="enable-composer-autoload-and-hooks"></a> Enable Composer _autoload_ and _hooks_
For Luthier CI to work, it's necessary that both the Composer **autoload** and the **hooks** are enabled in the framework. In the file `config.php` modify the following:
```php
<?php
# application/config/config.php
// (...)
$config['enable_hooks'] = TRUE;
$config['composer_autoload'] = TRUE;
// (...)
```
#### <a name="connect-luthier-ci-with-your-application"></a> Connect Luthier CI with your application
In the `hooks.php` file, assign the Luthier CI hooks to the `$hook` variable:
```php
<?php
# application/config/hooks.php
defined('BASEPATH') OR exit('No direct script access allowed');
// (...)
$hook = Luthier\Hook::getHooks();
```
In the `routes.php` file, assign the Luthier CI routes to the `$route` variable:
```php
<?php
# application/config/routes.php
defined('BASEPATH') OR exit('No direct script access allowed');
// (...)
$route = Luthier\Route::getRoutes();
```
### <a name="initialization"></a> Initialization
The first time that Luthier CI is executed some files and folders are created automatically:
* `routes/web.php`: HTTP routes file
* `routes/api.php`: AJAX routes file
* `routes/cli.php`: CLI routes file
* `controllers/Luthier.php`: Fake controller, necessary to use some routes
* `middleware`: Folder to save the middleware files
During the initialization of the framework the hooks are called: `Luthier\Hook::getHooks()` returns an array with the hooks used by Luthier CI, including the one needed to boot it. At this point, Luthier CI analyzes and compiles all the routes defined in the first three files mentioned above. Then, when the framework loads the routes in the `application/config/routes.php` file, `Luthier\Route::getRoutes()` returns an array with the routes in the format that CodeIgniter understands. All the following is the normal execution of the framework.
<div class="alert alert-warning">
<i class="fa fa-warning" aria-hidden="true"></i>
<strong>Writing permissions</strong>
<br />
If you get errors during the creation of the Luthier CI base files, it may be due to insufficient permissions. Make sure that the <code>application</code> folder has write permission
</div>
[//]: # ([author] Anderson Salas, translated by Julio Cedeño)
[//]: # ([meta_description] Luthier CI routes also work for the command line, and here we explain how to use them)
# Command line
### Contents
1. [Introduction](#introduction)
2. [Syntax](#syntax)
3. [Using CLI routes](#using-cli-routes)
4. [Built-in CLI tools](#built-in-cli-tools)
1. [Activation](#activation)
2. ['luthier make' command](#luthier-make)
3. ['luthier migrate' command](#luthier-migrate)
### <a name="introduction"></a> Introduction
Thanks to Luthier CI you can take advantage of the possibilities offered by the framework through the command line interface (CLI).
### <a name="syntax"></a> Sintaxis
The CLI routes are similar to the HTTP and AJAX routes in their syntax. CLI routes must be defined in the `application/routes/cli.php` file
Example:
```php
<?php
# application/routes/cli.php
// Using anonymous functions
Route::cli('test', function(){ // <- (note that here the method is 'cli' and not 'get', 'post', etc.)
echo 'Hello world!';
});
// Pointing to an existing controller
Route::cli('test2', 'foo@bar');
```
CLI routes share the same properties as their HTTP/AJAX counterparts, you can learn more about them [here](./routes#syntax).
### <a name="using-cli-routes"></a> Using CLI routes
To access the CLI routes you must call the PHP interpreter from the command line in the `index.php` file of the root folder of your application, separating each segment of the desired route with spaces, for example:
```
$ php path/to/app/index.php [segment1] [segument2] ... [segmentN]
```
So, having this route:
```php
Route::cli('make/controller/{name}', function($name){
echo 'Making the controller ' . $name ;
});
```
It can be accessed by running:
```
$ php path/to/app/index.php make controller test
```
And the result would be:
```
Making the controller test
```
### <a name="built-in-cli-tools"></a> Built-in CLI tools
As of version 0.2.0 Luthier CI comes with several command line tools that will help you with some repetitive tasks.
<div class="alert alert-warning">
<i class="fa fa-warning" aria-hidden="true"></i>
<strong>Writing permissions</strong>
<br />
Make sure that the <code>application</code> folder has write permissions so that these commands work correctly
</div>
<div class="alert alert-info">
<i class="fa fa-info-circle" aria-hidden="true"></i>
<strong>Only available for development</strong>
<br />
For security reasons, these commands will be disabled if your application is configured with the <code>testing</code> or <code>production</code> environments
</div>
#### <a name="activation"></a> Activation
CLI tools are disabled by default. To activate them, just add a couple of lines to your routes file:
```php
<?php
# application/routes/cli.php
Luthier\Cli::maker(); // 'luthier make' command
Luthier\Cli::migrations(); // 'luthier migrate' command
```
#### <a name="luthier-make"></a> <kbd>luthier make</kbd> command
This allows generating a wide variety of framework files.
Syntax:
```
$ php index.php luthier make [resource] [name] [type?(sequenatial|date)=date]
```
Where `resource` is the resource type (`controller`, `model`, ` helper`, `library`, ` middleware` or `migration`), `name` is the name
of the resource and `type` (in case of creating a migration) is the type of migration to generate.
Examples:
```
// Creating a controller:
$ php index.php luthier make controller ControllerName
// Creating a model:
$ php index.php luthier make model ModelName
// Creating a library:
$ php index.php luthier make library LibraryName
// Creating a helper:
$ php index.php luthier make helper HelperName
// Creating a middleware:
$ php index.php luthier make middleware MiddlewareName
// Creating a migration (by default, migrations are created by date)
$ php index.php luthier make migration create_users_table
$ php index.php luthier make migration create_users_table date
$ php index.php luthier make migration create_users_table sequential
```
#### <a name="luthier-migrate"></a> <kbd>luthier migrate</kbd> command
Runs (or rollback) a migration.
Syntax:
```
$ php index.php luthier migrate [version?=latest]
```
Where `version` is the version of the migration to run. If it's omitted, it will proceed to migrate to the latest available version.
It's also possible to use one of these special values as `version`:
* `reverse`: reverses ALL migrations
* `refresh`: reverses ALL migrations and then proceeds to migrate to the latest available version
Examples:
```
$ php index.php luthier migrate reverse
$ php index.php luthier migrate refresh
```
[//]: # ([author] Anderson Salas, translated by Julio Cedeño)
[//]: # ([meta_description] Explore the concept of Middleware that Luthier CI introduces into your CodeIgniter applications and learn to use it with practical examples)
# Middleware
### Contents
1. [Introduction](#introduction)
2. [Middleware execution points](#middleware-execution-points)
3. [Create a middleware](#create-a-middleware)
4. [Assign a middleware](#assign-a-middleware)
1. [Global Middleware](#global-middleware)
2. [Route middleware](#route-middleware)
5. [Run a middleware](#run-a-middleware)
1. [Middleware parameters](#middleware-parameters)
2. [External middleware](#external-middleware)
### <a name="introduction"></a> Introduction
Think of middleware as a set of _layers_ that requests must go through in your application in order to reach a resource.
With the middleware you can, for example, validate that a user is logged in and has sufficient permissions to access certain sections of your application, and redirect it to another place otherwise.
The middleware is, in fact, an extension of the controller, because the singleton of the framework has already been built at this point and you can get it using the `ci()` function.
### <a name="middleware-execution-points"></a> Middleware execution points
Two execution points are available:
* `pre_controller`: the middleware defined at this point will be executed after the controller constructor, _BUT_ before any controller action is performed.
* `post_controller`: the middleware defined at this point will run exactly on the native `post_controller` hook of CodeIgniter.
<div class="alert alert-warning">
<i class="fa fa-warning" aria-hidden="true"></i>
<strong>The controller constructor always executed first</strong>
<br />
This is the behavior of CodeIgniter and Luthier CI does not modify it.
</div>
It's possible that at some point you need to execute code before the middleware, the way to do it is by defining a public method in your controller called `preMiddleware`:
```php
<?php
# application/controllers/TestController.php
defined('BASEPATH') OR exit('No direct script access allowed');
class TestController extends CI_Controller
{
public function preMiddleware()
{
// This will be executed after the constructor (if it exists), but before the middleware
}
}
```
<div class="alert alert-warning">
<i class="fa fa-warning" aria-hidden="true"></i>
<strong>Not available in callbacks as routes</strong>
<br />
When you use callbacks as routes there is no way to execute arbitrary code before the middleware
</div>
### <a name="create-a-middleware"></a> Create a middleware
All middleware must be saved in the `application/middleware` folder. A middleware is any PHP class with a `run()` public method.
Example:
```php
<?php
# application/middleware/TestMiddleware.php
class TestMiddleware implements Luthier\MiddlewareInterface
{
public function run()
{
// This is the entry point of the middleware
}
}
```
<div class="alert alert-warning">
<i class="fa fa-warning" aria-hidden="true"></i>
<strong>Implementing the <code>MiddlewareInterface</code> interface will be mandatory</strong>
<br />
As of 0.3.0 version, the use of Middleware classes that do not implement the <code>Luthier\MiddlewareInterface </code> interface is DEPRECATED and will stop working in the next version</div>
In order to assign a middleware in your application it's necessary that both the name of the class and the name of the file are exactly the same. Also, be careful not to use the same name as some other resource in the framework, such as a controller, model, library, etc.
<div class="alert alert-success">
<i class="fa fa-check" aria-hidden="true"></i>
<strong>Add <em>Middleware</em> suffix</strong>
<br />
One way to avoid conflicts is by adding the <em>Middleware</em> suffix to the middleware name.
</div>
<div class="alert alert-success">
<i class="fa fa-check" aria-hidden="true"></i>
<strong>Create a middleware from the command line</strong>
<br />
If you have activated the built-in CLI tools of Luthier CI, use the <code>luthier make middleware [name]</code> command to create a new middleware
</div>
### <a name="assign-a-middleware"></a> Assign a middleware
You can assign a middleware in different contexts of your application:
#### <a name="global-middleware"></a> Global middleware
To define a middleware in a **global** context, use this syntax:
```php
Route::middleware([name], [exec_point?]);
```
Where `name` is the name of the middleware and `exec_point` is the execution point, which by default is `pre_controller`.
You can use an anonymous function instead of the name of a middleware:
```php
Route::middleware(function(){
ci()->load->view('global_header');
});
```
#### <a name="route-middleware"></a> Route middleware
In the **route group** context, middleware is another property, so it goes in the third argument of the `group()` method:
```php
Route::group('site', ['middleware' => ['AuthMiddleware']], function(){
});
```
Finally, in the **individual route** context, middleware is also another property, so it goes in the second argument:
```php
Route::put('foo/bar','controller@method', ['middleware' => ['TestMiddleware']]);
```
<div class="alert alert-warning">
<i class="fa fa-warning" aria-hidden="true"></i>
<strong>Only at the pre_controller point</strong>
<br />
When you assign a middleware to routes and route groups, the execution point is ALWAYS <code>pre_controller</code>
</div>
### <a name="run-a-middleware"></a> Run a middleware
For run a middleware from a controller, use the `run()` method of the `middleware` property:
```php
<?php
# application/controllers/TestController.php
defined('BASEPATH') OR exit('No direct script access allowed');
class TestController extends CI_Controller
{
public function __construct()
{
$this->middleware->run('AuthMiddleware');
}
}
```
#### <a name="middleware-parameters"></a> Middleware parameters
The `run()` method of the `middleware` property supports a second argument with the middleware parameters:
```php
// $args can be any variable type:
$args = ['foo' => 'bar'];
$this->middleware->run('AuthMiddleware', $args);
````
#### <a name="external-middleware"></a> External middleware
It is possible to run middleware from an external class, as long as it has a public method called `run()`
```php
<?php
# application/controllers/TestController.php
defined('BASEPATH') OR exit('No direct script access allowed');
use Vendor\CustomMiddleware;
class TestController extends CI_Controller
{
public function __construct()
{
$this->middleware->run(new CustomMiddleware());
}
}
```
[//]: # ([author] Julio Cedeño)
[//]: # ([meta_description] Luthier CI includes powerful user authentication tools, inspired by Symfony, so you can worry about what really matters about your application)
# Authentication
### Introduction
CodeIgniter includes all the necessary tools to build a user authentication system. Unfortunately, it lacks an integrated interface or library that's easy to implement, maintain and scale.
Luthier CI tackles the problem using an authentication model inspired by Symfony, which looks for as much flexibility as possible so that the developer can start working quickly, without needing to reinvent the wheel.
### Activation
As an optional module, the Luthier CI authentication functions must be activated first. To do so, go to the `application/config/hooks.php` file and replace it:
```php
<?php
# application/config/hooks.php
defined('BASEPATH') OR exit('No direct script access allowed');
// (...)
$hook = Luthier\Hook::getHooks();
```
With:
```php
<?php
# application/config/hooks.php
defined('BASEPATH') OR exit('No direct script access allowed');
// (...)
$hook = Luthier\Hook::getHooks(
[
'modules' => ['auth']
]
);
```
### Authentication tools available
The authentication of Luthier CI comes in two flavors: **SimpleAuth** and the **Luthier CI Authentication Framework**.
#### SimpleAuth: the fastest and funniest way
If what you need is a pre-configured, customizable and easy-to-use authentication system, **SimpleAuth** is perfect for you. It has been designed for the most common case of authentication: the traditional login through a form and a database.
Some of its features:
* Login screen and user registration
* Verification of email when registering
* Password reset
* User Roles
* "Remind me" functionality based on cookies (optional)
* Access Control Lists (ACL) (optional)
* It works with all CodeIgniter database drivers
* Protection against brute force attacks during login (optional)
* Automatic definition of routes (With the method `Route::auth()`)
* Multiple templates available to choose from, translated into several languages
#### Luthier CI Authentication Framework: for advanced users
The **Luthier CI Authentication Framework** is a set of classes and interfaces that define the user authentication process abstractly. With it, you can perform the following tasks:
* Load of **User Providers**
* Login by username and password
* Forced login (bypass) using a username
* Validation of authentication status
* Validation of user roles
* Validation of user permissions through Access Control Lists (ACL)
* Management of session variables related to user authentication
* Driver-based authentication
Note that the Library is the basis for authentication, but its implementation depends on you!
[//]: # ([author] Anderson Salas)
[//]: # ([meta_description] You can add PHP Debug Bar to your application thanks to the integration of Luthier CI with this fantastic tool)
# Debug
<div class="alert alert-warning">
<i class="fa fa-warning" aria-hidden="true"></i>
<strong>Experimental feature</strong>
<br />
We have made an effort to make things work properly, but errors may occur rendering and / or charging of the assets required by this feature. Please <a href="https://github.com/ingeniasoftware/luthier-ci/issues/new">notify us</a> if you have had an incident during its use.
</div>
### Contents
1. [Introduction](#introduction)
2. [Activation](#activation)
3. [Debug messages](#debug-messages)
4. [Add your own data collectors](#add-your-own-data-collectors)
### <a name="introduction"></a> Introduction
You can add [PHP Debug Bar](http://phpdebugbar.com) to your application thanks to the integration of Luthier CI with this fantastic tool.
### <a name="activation"></a> Activation
To activate this feature (which is disabled by default) go to your `application/config/hooks.php` file and replace:
```php
<?php
# application/config/hooks.php
defined('BASEPATH') OR exit('No direct script access allowed');
// (...)
$hook = Luthier\Hook::getHooks();
```
With:
```php
<?php
# application/config/hooks.php
defined('BASEPATH') OR exit('No direct script access allowed');
// (...)
$hook = Luthier\Hook::getHooks(
[
'modules' => ['debug']
]
);
```
You should see the debug bar at the bottom of the window:
<p align="center">
<img src="https://ingenia.me/uploads/2018/06/19/luthier-ci-debugbar.png" alt="Luthier CI PHP Debug Bar" class="img-responsive" />
</p>
### <a name="debug-messages"></a> Debug messages
To add debug messages, use the `log()` static method of the `Luthier\Debug` class:
```php
# use Luthier\Debug;
Debug::log($variable, $type, $dataCollector);
```
Where `$variable` is the variable to debug, and `$type` is the type of message, which can be `'info'`, `'warning'` or `'error'`.
Example:
```php
<?php
# application/controllers/TestController.php
use Luthier\Debug;
defined('BASEPATH') OR exit('No direct script access allowed');
class TestController extends CI_Controller
{
public function index()
{
Debug::log('Welcome to Luthier-CI ' . LUTHIER_CI_VERSION . '!');
Debug::log('Hello world!','info');
Debug::log('This is a warning, watch out!','warning');
Debug::log('Oh snap! an error was occurred!','error');
$this->load->view('welcome_message');
}
}
```
And the result:
<p align="center">
<img src="https://ingenia.me/uploads/2018/06/19/luthier-ci-debugbar-log.png" alt="Luthier CI PHP Debug Bar" class="img-responsive" />
</p>
An optional `$dataCollector` argument is the name of the [data collector](http://phpdebugbar.com/docs/data-collectors.html) where the message will be stored:
```php
Debug::log('Custom data collector','error','my_custom_data_collector');
```
If you need to store a message to be shown in the next request (for example, after submitting a form) use the `logFlash()` method, whose syntax is identical to the `log()` static method:
```php
Debug::logFlash('Hey! this will be available in the next request','info');
```
<div class="alert alert-success">
<i class="fa fa-check" aria-hidden="true"></i>
<strong>Deactivated in production environments</strong>
<br />
If you set the environment of your application to <code>production</code> this feature will be automatically disabled, and any debugging code will be ignored
</div>
<div class="alert alert-warning">
<i class="fa fa-warning" aria-hidden="true"></i>
<strong>Requires that there is data in the output buffer</strong>
<br />
Luthier CI adds the PHP Debug Bar code in the output buffer BEFORE it is processed and sent to the browser by the <code> output</code> library of CodeIgniter. Therefore, it is necessary to have used at least once the function<code>$this->load-> view()</code> or have explicitly defined an output buffer to work on. The <code>echo</code> statements DO NOT produce any internal output buffer. In addition, stopping the execution of the script with the functions <code>die</code> or <code>exit</code> will prevent the PHP Debug Bar from being displayed.
</div>
### <a name="add-your-own-data-collectors"></a> Add your own data collectors
It is possible to add your own data collectors and store messages in them. To add a data collector to the PHP Debug Bar instance, use the `addCollector()` static method:
```php
# use Luthier\Debug;
Debug::addCollector(new MyCollector());
```
\ No newline at end of file
[//]: # ([author] Anderson Salas, translated by Julio Cedeño)
[//]: # ([meta_description] Look Luthier-CI in action! Here we compile some real examples of use so you can find inspiration)
# Examples
### Example # 1: Multi-language website
This is an example shows a multi-language website managed by the URL.
A middleware is used to load the current language file.
```php
<?php
# application/routes/web.php
Route::get('/', function(){
// Route "by default". This is a good place to request a cookie, session variable
    // or something that allows us to restore the last language of the user, or show a
    // language selection screen if no information is provided.
redirect(route('homepage', ['_locale' => 'en']));
});
Route::group('{((es|en|it|br|ge)):_locale}', ['middleware' => ['Lang_middleware']], function(){
Route::get('home', function(){
var_dump( ci()->lang->line('test') );
})->name('homepage');
Route::get('about', function(){
var_dump( ci()->lang->line('test') );
})->name('about');
});
```
```php
<?php
# application/middleware/Lang_middleware.php
class Lang_middleware
{
public function run()
{
// Obtaining the value of the "_locale" sticky parameter
$locale = ci()->route->param('_locale');
$langs = [
'es' => 'spanish',
'en' => 'english',
'it' => 'italian',
'br' => 'portuguese-brazilian',
'ge' => 'german',
];
ci()->lang->load('test', $langs[$locale]);
}
}
```
\ No newline at end of file
[//]: # ([author] Anderson Salas)
[//]: # ([meta_description] Lee la documentación oficial de Luthier CI y descubre las posibilidades que te ofrece, mira ejemplos, casos de uso y mucho más)
# Bienvenido
### Acerca de Luthier CI
**Luthier CI** es un complemento para CodeIgniter que añade interesantes características pensadas para facilitar la construcción de sitios web grandes y APIs en general. Fué hecho para integrarse lo mejor posible con el framework, de modo que todo lo que ya existe en tu aplicación debe seguir funcionando sin problemas luego de instalar Luthier CI.
Esta documentación asume que tienes conocimientos básicos sobre CodeIgniter. Si nunca has usado CodeIgniter, un buen punto de partida es su [documentación oficial](https://www.codeigniter.com/user_guide) (en inglés)
Luthier CI es software libre y está disponible bajo una licencia MIT.
### Características
#### Enrutamiento mejorado
Luthier CI reemplaza la forma en que defines las rutas en tu aplicación por una sintaxis inspirada en Laravel.
Por ejemplo, en lugar de definir un enorme arreglo de rutas parecido a esto:
```php
$route['catalog/cars/(:any)']['GET'] = 'CarsController/catalog/$1';
$route['catalog/cars/(:any)/(:any)']['GET'] = 'CarsController/catalog/$1/$2';
$route['catalog/bikes/(:any)']['GET'] = 'BikesController/catalog/$1';
$route['catalog/bikes/(:any)']['POST'] = 'BikesController/catalog/$1';
$route['catalog/bikes/(:any)/(:any)']['GET'] = 'BikesController/catalog/$1/$2';
$route['catalog/bikes/(:any)/(:any)']['POST'] = 'BikesController/catalog/$1/$2';
$route['catalog/airplanes/(:any)']['GET'] = 'AirplanesController/catalog/$1/$2';
$route['catalog/airplanes/(:any)/(:any)']['GET'] = 'AirplanesController/catalog/$1/$2';
```
...puedes escribir lo mismo de forma más compacta:
```php
Route::group('catalog', function(){
Route::get('cars/{category_id}/{filter_by?}', 'CarsController@catalog');
Route::match(['get','post'], 'bikes/{category_id}/{filter_by?}', 'BikesController@catalog');
Route::get('airplanes/{category_id}/{filter_by?}', 'AirplanesController@catalog');
});
```
Además, Luthier CI te ayuda a mantener tus rutas organizadas, pues cada tipo de ruta tiene su propio archivo donde debe definirse: hay un archivo para rutas HTTP, otro para rutas AJAX y otro para rutas CLI.
#### Middleware
Luthier CI introduce el concepto de _Middleware_ en el framework.
Usado correctamente, el middleware puede ayudarte a crear filtros y acciones en tus controladores que, de otra forma, serían muy tediosas de implementar usando _librerías_ y _helpers_.
Puedes usar el middleware tanto en rutas específicas como en grupos de rutas, o incluso a nivel global en tu aplicación.
#### Fácil instalación
Luthier CI se instala a través de Composer y utiliza los _hooks_ de CodeIgniter para integrase en tu aplicación. Olvídate de copiar o mover archivos o de seguir listas enormes de pasos para poner a funcionar Luthier CI ¡en la mayoría de los casos la instalación no toma más de 5 minutos!
### Comunidad y soporte
Para reportar errores y proponer cambios por favor visita el repositorio de [Luthier CI en Github](https://github.com/ingeniasoftware/luthier-ci)
\ No newline at end of file
[//]: # ([author] Anderson Salas)
[//]: # ([meta_description] Aprende cómo obtener Luthier CI e instalarlo en tu aplicación de CodeIgniter con instrucciones paso a paso ¡no toma más de 5 minutos!)
# Instalación
### Contenido
1. [Requisitos](#requirements)
2. [Instalación](#installation)
1. [Obtener Luthier CI](#get-luthier-ci)
2. [Habilitar el autoload de Composer y los hooks](#enable-composer-autoload-and-hooks)
3. [Conectar Luthier CI con tu aplicación](#connect-luthier-ci-with-your-application)
3. [Inicialización](#initialization)
### <a name="requirements"></a> Requisitos
* PHP >= 5.6 (Compatible con PHP 7)
* CodeIgniter >= 3.0
### <a name="installation"></a> Instalación
#### <a name="get-luthier-ci"></a> Obtener Luthier CI
<div class="alert alert-info">
<i class="fa fa-info-circle" aria-hidden="true"></i>
<strong>Composer requerido</strong>
<br />
Luthier CI se instala a través de Composer. Puedes obtenerlo <a href="https://getcomposer.org/download/">aquí</a>.
</div>
Dirígete a la carpeta `application` y ejecuta el siguiente comando:
```bash
composer require luthier/luthier
```
#### <a name="enable-composer-autoload-and-hooks"></a> Habilitar el _autoload_ de Composer y los _hooks_
Para que Luthier CI funcione es necesario que tanto el **autoload** de Composer y como los **hooks** estén habilitados. En el archivo `config.php` modifica lo siguiente:
```php
<?php
# application/config/config.php
// (...)
$config['enable_hooks'] = TRUE;
$config['composer_autoload'] = TRUE;
// (...)
```
#### <a name="connect-luthier-ci-with-your-application"></a> Conectar Luthier CI con tu aplicación
En el archivo `hooks.php`, asigna los hooks de Luthier CI a la variable `$hook`:
```php
<?php
# application/config/hooks.php
defined('BASEPATH') OR exit('No direct script access allowed');
// (...)
$hook = Luthier\Hook::getHooks();
```
En el archivo `routes.php`, asigna las rutas de Luthier CI a la variable `$route`:
```php
<?php
# application/config/routes.php
defined('BASEPATH') OR exit('No direct script access allowed');
// (...)
$route = Luthier\Route::getRoutes();
```
### <a name="initialization"></a> Inicialización
La primera vez que Luthier CI se ejecuta algunos archivos y carpetas son creados automáticamente:
* `routes/web.php`: Archivo de rutas HTTP
* `routes/api.php`: Archivo de rutas AJAX
* `routes/cli.php`: Archivo de rutas CLI
* `controllers/Luthier.php`: Controlador falso, necesario para usar algunas rutas
* `middleware`: Carpeta para guardar los archivos de middleware
Durante la inicialización del framework los _hooks_ son llamados: `Luthier\Hook::getHooks()` devuelve un arreglo con los hooks usados por Luthier CI, incluído el necesario para su arranque. En este punto, Luthier CI analiza y compila todas las rutas definidas en los tres primeros archivos mencionados anteriormente. Entonces, cuando el framework carga las rutas en el archivo `application/config/routes.php`, `Luthier\Route::getRoutes()` devuelve un arreglo con las rutas en el formato que CodeIgniter entiende. Todo lo siguiente es la ejecución normal del framework.
<div class="alert alert-warning">
<i class="fa fa-warning" aria-hidden="true"></i>
<strong>Permisos de escritura</strong>
<br />
Si obtienes errores durante la creación de los archivos base de Luthier CI, es posible que se deba a permisos insuficientes. Asegúrate de que la carpeta <code>application</code> tenga permisos de escritura
</div>
\ No newline at end of file
[//]: # ([author] Anderson Salas)
[//]: # ([meta_description] Las rutas de Luthier CI también funcionan para la línea de comandos, y aquí te explicamos cómo usarlas)
# Línea de Comandos
### Contenido
1. [Introducción](#introduction)
2. [Sintaxis](#syntax)
3. [Usando rutas CLI](#using-cli-routes)
4. [Herramientas CLI incorporadas](#built-in-cli-tools)
1. [Activación](#activation)
2. [Comando 'luthier make'](#luthier-make)
3. [Comando 'luthier migrate'](#luthier-migrate)
### <a name="introduction"></a> Introducción
Gracias a Luthier CI puedes aprovechar aún más las posibilidades que ofrece el framework a través de la interfaz de línea de comandos (CLI)
### <a name="syntax"></a> Sintaxis
Las rutas CLI son parecidas a las rutas HTTP y AJAX en cuanto a su sintaxis. Éstas rutas se deben definir en el archivo `application/routes/cli.php`
Ejemplo:
```php
<?php
# application/routes/cli.php
// Usando funciones anónimas
Route::cli('test', function(){ // <- (nota que aquí el método es 'cli' y no 'get', 'post', etc.)
echo 'Hello world!';
});
// Apuntando a un controlador existente
Route::cli('test2', 'foo@bar');
```
Las rutas CLI comparten las mismas propiedades de sus homólogas HTTP/AJAX, puedes aprender más sobre ellas [aquí](./routes#syntax).
### <a name="using-cli-routes"></a> Usando rutas CLI
Para acceder a las rutas CLI debes llamar al intérprete de PHP desde la línea de comandos en el archivo `index.php` de la carpeta raíz de tu aplicación, separando con espacios cada segmento de la ruta deseada, por ejemplo:
```
$ php path/to/app/index.php [segment1] [segument2] ... [segmentN]
```
Así pues, teniendo esta ruta:
```php
Route::cli('make/controller/{name}', function($name){
echo 'Making the controller ' . $name ;
});
```
Se puede acceder a ella ejecutando:
```
$ php path/to/app/index.php make controller test
```
Y el resultado sería:
```
Making the controller test
```
### <a name="built-in-cli-tools"></a> Herramientas para CLI incorporadas
A partir de la versión 0.2.0 Luthier CI viene con varias herramientas para línea de comandos que te ayudarán con algunas tareas repetitivas.
<div class="alert alert-warning">
<i class="fa fa-warning" aria-hidden="true"></i>
<strong>Permisos de escritura</strong>
<br />
Asegúrate de que la carpeta <code>application</code> tenga permisos de escritura para que estos comandos funcionen correctamente
</div>
<div class="alert alert-info">
<i class="fa fa-info-circle" aria-hidden="true"></i>
<strong>Sólo disponibles para desarrollo</strong>
<br />
Por motivos de seguridad, éstos comandos se desactivarán si tu aplicación está configurada con los entornos <code>testing</code> o <code>production</code>
</div>
#### <a name="activation"></a> Activación
Las herramientas CLI vienen desactivadas por defecto. Para activarlas, sólo basta con añadir un par de líneas a tu archivo de rutas:
```php
<?php
# application/routes/cli.php
Luthier\Cli::maker(); // Comando 'luthier make'
Luthier\Cli::migrations(); // Comando 'luthier migrate'
```
#### <a name="luthier-make"></a> Comando <kbd>luthier make</kbd>
Permite generar una amplia variedad de archivos del framework.
Sintaxis:
```
$ php index.php luthier make [resource] [name] [type?(sequenatial|date)=date]
```
Donde `resource` es el tipo de recurso (`controller`, `model`, `helper`, `library`, `middleware` o `migration`), `name` es el nombre
del recurso y `type` (en caso de crear una migración) es el tipo de migración a generar.
Ejemplos:
```
// Creando un controlador:
$ php index.php luthier make controller ControllerName
// Creando un modelo:
$ php index.php luthier make model ModelName
// Creando una librería:
$ php index.php luthier make library LibraryName
// Creando un helper:
$ php index.php luthier make helper HelperName
// Creando un middleware:
$ php index.php luthier make middleware MiddlewareName
// Creando una migración (por defecto, las migraciones son creadas por fecha)
$ php index.php luthier make migration create_users_table
$ php index.php luthier make migration create_users_table date
$ php index.php luthier make migration create_users_table sequential
```
#### <a name="luthier-migrate"></a> Comando <kbd>luthier migrate</kbd>
Corre (o revierte) una migración.
Sintaxis:
```
$ php index.php luthier migrate [version?=latest]
```
Donde `version` es la versión de la migración a correr. Si se omite, se procederá a migrar a la última versión disponible.
Tambien es posible utilizar uno de estos comandos especiales como `version`:
* `reverse`: revierte TODAS las migraciones
* `refresh`: revierte TODAS las migraciones y luego procede a migrar a la última versión disponible
Ejemplos:
```
$ php index.php luthier migrate reverse
$ php index.php luthier migrate refresh
```
[//]: # ([author] Anderson Salas)
[//]: # ([meta_description] Explora el concepto de Middleware que Luthier CI introduce en tus aplicaciones de CodeIgniter y aprende a utilizarlo con ejemplos prácticos)
# Middleware
### Contenido
1. [Introducción](#introduction)
2. [Puntos de ejecución de middleware](#middleware-execution-points)
3. [Crear un middleware](#create-a-middleware)
4. [Asignar un middleware](#assign-a-middleware)
1. [Middleware global](#global-middleware)
2. [Middleware de ruta](#route-middleware)
5. [Ejecutar un middleware](#run-a-middleware)
1. [Parámetros de middleware](#middleware-parameters)
2. [Middleware externo](#external-middleware)
### <a name="introduction"></a> Introducción
Piensa en el middleware como una serie de _capas_ que deben atravesar las solicitudes hechas a un recurso de tu aplicación para poder llegar a él.
Con el middleware puedes, por ejemplo, validar que un usuario esté logueado y tenga permisos suficientes para de acceder a ciertas secciones de tu aplicación, y redirigirlo a otro lugar en caso contrario.
El middleware es, de hecho, una extensión del controlador, porque el _singleton_ del framework ya se ha construído en este punto y puedes obtenerlo usando la funcion `ci()`.
### <a name="middleware-execution-points"></a> Puntos de ejecución de middleware
Están disponibles dos puntos de ejecución:
* `pre_controller`: el middleware definido en este punto se ejecutará después del constructor del controlador, _PERO_ antes de que cualquier acción del controlador sea efectuada.
* `post_controller`: el middleware definido en este punto se ejecutará exactamente en el hook `post_controller` nativo de CodeIgniter.
<div class="alert alert-warning">
<i class="fa fa-warning" aria-hidden="true"></i>
<strong>El constructor del controlador siempre se ejecuta primero</strong>
<br />
Este es el comportamiento de CodeIgniter y Luthier CI no lo modifica.
</div>
Es posible que en algún momento requieras ejecutar código antes del middleware, la manera de hacerlo es definiendo un método público en tu controlador llamado `preMiddleware`:
```php
<?php
# application/controllers/TestController.php
defined('BASEPATH') OR exit('No direct script access allowed');
class TestController extends CI_Controller
{
public function preMiddleware()
{
// Esto se ejecutará después del constructor (si existe), pero antes del middleware
}
}
```
<div class="alert alert-warning">
<i class="fa fa-warning" aria-hidden="true"></i>
<strong>No disponible en funciones anónimas como rutas</strong>
<br />
Cuando usas funciones anónimas como rutas no existe una forma de ejecutar código arbitrario antes del middleware
</div>
### <a name="create-a-middleware"></a> Crear un middleware
Todo el middleware debe guardarse en la carpeta `application/middleware`. Un middleware es cualquier clase PHP que implemente la interfaz `Luthier\MiddlewareInterface`, con un método público llamado `run()`.
Ejemplo:
```php
<?php
# application/middleware/TestMiddleware.php
class TestMiddleware implements Luthier\MiddlewareInterface
{
public function run()
{
// Este es el punto de entrada del middleware
}
}
```
<div class="alert alert-warning">
<i class="fa fa-warning" aria-hidden="true"></i>
<strong>Implementar la interfaz <code>MiddlewareInterface</code> será obligatorio</strong>
<br />
A partir de la versión 0.3.0 el uso de clases de Middleware que no implementen la interfaz <code>Luthier\MiddlewareInterface</code> está OBSOLETO y dejará de funcionar en la próxima versión
</div>
Para poder asignar un middleware en tu aplicación es necesario que tanto el nombre de la clase como el nombre el archivo sean exactamente iguales. Además, debes tener cuidado de no usar el mismo nombre de algún otro recurso del framework, como un controlador, modelo, librería, etc.
<div class="alert alert-success">
<i class="fa fa-check" aria-hidden="true"></i>
<strong>Añade el sufijo <em>Middleware</em></strong>
<br />
Una forma de evitar conflictos es añadiendo el sufijo <em>Middleware</em> al nombre del middleware.
</div>
<div class="alert alert-success">
<i class="fa fa-check" aria-hidden="true"></i>
<strong>Crea un middleware desde la linea de comandos</strong>
<br />
Si has activado las herramientas CLI integradas de Luthier CI, usa el comando <code>luthier make middleware [nombre]</code> para crear un nuevo middleware
</div>
### <a name="assign-a-middleware"></a> Asignar un middleware
Puedes asignar un middleware en diferentes contextos de tu aplicación:
#### <a name="global-middleware"></a> Middleware global
Para definir un middleware en un contexto **global**, la sintaxis es la siguiente:
```php
Route::middleware([name], [exec_point?]);
```
Donde `name` es el nombre del middleware y `exec_point` es el punto de ejecución, que por defecto es `pre_controller`.
Puedes usar una función anónima en lugar del nombre de un middleware:
```php
Route::middleware(function(){
ci()->load->view('global_header');
});
```
#### <a name="route-middleware"></a> Middleware de ruta
En el contexto de un **grupo de rutas**, el middleware es otra propiedad más, así que va en el segundo argumento del método `group()`:
```php
Route::group('site', ['middleware' => ['AuthMiddleware']], function(){
});
```
Por último, en el contexto de una **ruta individual**, el middleware es también otra propiedad más, así que va en el tercer argumento:
```php
Route::put('foo/bar','controller@method', ['middleware' => ['TestMiddleware']]);
```
<div class="alert alert-warning">
<i class="fa fa-warning" aria-hidden="true"></i>
<strong>Sólo en el punto pre_controller</strong>
<br />
Cuando asignas un middleware a rutas y grupos de rutas, el punto de ejecución SIEMPRE es <code>pre_controller</code>
</div>
### <a name="run-a-middleware"></a> Ejecutar un middleware
Para ejecutar un middleware desde un controlador usa el método `run()` de la propiedad `middleware`:
```php
<?php
# application/controllers/TestController.php
defined('BASEPATH') OR exit('No direct script access allowed');
class TestController extends CI_Controller
{
public function __construct()
{
$this->middleware->run('AuthMiddleware');
}
}
```
#### <a name="middleware-parameters"></a> Parámetros de middleware
El método `run()` de la propiedad `middleware` admite un segundo argumento con los parámetros del middleware:
```php
// $args puede ser cualquier tipo de variable:
$args = ['foo' => 'bar'];
$this->middleware->run('AuthMiddleware', $args);
````
#### <a name="external-middleware"></a> Middleware externo
Es posible ejecutar middleware a partir de una clase externa, siempre y cuando posea un método público llamado `run()`
```php
<?php
# application/controllers/TestController.php
defined('BASEPATH') OR exit('No direct script access allowed');
use Vendor\CustomMiddleware;
class TestController extends CI_Controller
{
public function __construct()
{
$this->middleware->run(new CustomMiddleware());
}
}
```
\ No newline at end of file
[//]: # ([author] Anderson Salas)
[//]: # ([meta_description] Luthier CI incluye poderosas herramientas de autenticación de usuarios, inspiradas en Symfony, para que te preocupes por lo que realmente importa de tu aplicación)
# Autenticación
### Introducción
CodeIgniter incluye todas las herramientas necesarias para construir un sistema de autenticación de usuario. Desafortunadamente, carece de una interfaz o librería integrada que sea fácil de implementar, mantener y escalar.
Luthier CI aborda el problema usando un modelo de autenticación inspirado en Symfony, con el que se busca la mayor flexibilidad posible para que el desarrollador pueda comenzar a trabajar rápidamente, sin necesidad de reinventar la rueda.
### Activación
Al ser un módulo opcional, la funciones de autenticación de Luthier CI deben activarse primero. Para hacerlo, ve al archivo `application/config/hooks.php` y reemplaza:
```php
<?php
# application/config/hooks.php
defined('BASEPATH') OR exit('No direct script access allowed');
// (...)
$hook = Luthier\Hook::getHooks();
```
Por:
```php
<?php
# application/config/hooks.php
defined('BASEPATH') OR exit('No direct script access allowed');
// (...)
$hook = Luthier\Hook::getHooks(
[
'modules' => ['auth']
]
);
```
### Herramientas de autenticación disponibles
La autenticación de Luthier CI viene en dos sabores: **SimpleAuth** y el **Framework de Autenticación de Luthier CI**.
#### SimpleAuth: la forma más rápida y divertida
Si lo que necesitas es un sistema de autenticación pre-configurado, personalizable y fácil de usar, **SimpleAuth** es perfecto para ti. Ha sido diseñado para el caso más común de autenticación: el inicio de sesión tradicional a través de un formulario y una base de datos.
Algunas de sus características:
* Pantalla de inicio de sesión y registro de usuario
* Verificación de correo electrónico al registrarse
* Restablecimiento de contraseña
* Roles de usuario
* Funcionalidad "Recuérdame" basada en cookies (opcional)
* Listas de Control de Acceso (ACL) (opcional)
* Funciona con todos los drivers de bases de datos de CodeIgniter
* Protección contra ataques de fuerza bruta durante el inicio de sesión (opcional)
* Definición automática de rutas (Con el método `Route::auth()`)
* Múltiples plantillas disponibles para elegir, traducidas a varios idiomas
#### Framework de Autenticación de Luthier CI: para usuarios avanzados
El **Framework de Autenticación de Luthier CI** es un conjunto de clases e interfaces que definen el proceso de autenticación de usuario de forma abstracta. Con él, podrás realizar las siguientes tareas:
* Carga de **Proveedores de usuario**
* Inicio de sesión mediante usuario y contraseña
* Inicio de sesión forzada (bypass) mediante nombre de usuario
* Validación de estado de autenticación
* Validación de roles de usuario
* Validación de permisos de usuario a través de Listas de Control de Acceso (ACL)
* Manejo de las variables de sesión relacionadas a la autenticación de usuario
* Autenticación basada en controladores
Nota que la Librería constituye la base de la autenticación ¡pero su implementación depende de ti!
[//]: # ([author] Anderson Salas)
[//]: # ([meta_description] Puedes añadir PHP Debug Bar a tu aplicación gracias a la integración de Luthier CI con esta fantástica herramienta. )
# Depuración
<div class="alert alert-warning">
<i class="fa fa-warning" aria-hidden="true"></i>
<strong>Característica experimental</strong>
<br />
Hemos hecho un esfuerzo para que todo funcione correctamente, pero es posible que ocurran errores de renderizado y/o carga de los assets requeridos por esta característica. Por favor, <a href="https://github.com/ingeniasoftware/luthier-ci/issues/new">notifícanos</a> si has tenido algún incidente durante su uso.
</div>
### Contenido
1. [Introducción](#introduction)
2. [Activación](#activation)
3. [Mensajes de depuración](#debug-messages)
4. [Añadir tus propios recolectores de datos](#add-your-own-data-collectors)
### <a name="introduction"></a> Introducción
Puedes añadir [PHP Debug Bar](http://phpdebugbar.com) a tu aplicación gracias a la integración de Luthier CI con esta fantástica herramienta.
### <a name="activation"></a> Activación
Para activar esta característica (que está desactivada por defecto) ve a tu archivo `application/config/hooks.php` y reemplaza:
```php
<?php
# application/config/hooks.php
defined('BASEPATH') OR exit('No direct script access allowed');
// (...)
$hook = Luthier\Hook::getHooks();
```
Por:
```php
<?php
# application/config/hooks.php
defined('BASEPATH') OR exit('No direct script access allowed');
// (...)
$hook = Luthier\Hook::getHooks(
[
'modules' => ['debug']
]
);
```
Deberás ver la barra de depuración en la parte inferior de la ventana:
<p align="center">
<img src="https://ingenia.me/uploads/2018/06/19/luthier-ci-debugbar.png" alt="Luthier CI PHP Debug Bar" class="img-responsive" />
</p>
### <a name="debug-messages"></a> Mensajes de depuración
Para añadir mensajes de depuración, usa el método estático `log()` de la clase `Luthier\Debug`:
```php
# use Luthier\Debug;
Debug::log($variable, $type, $dataCollector);
```
Donde `$variable` es la variable a depurar, y `$type` es el tipo de mensaje, que puede ser `'info'`, `'warning'` o `'error'`.
Ejemplo:
```php
<?php
# application/controllers/TestController.php
use Luthier\Debug;
defined('BASEPATH') OR exit('No direct script access allowed');
class TestController extends CI_Controller
{
public function index()
{
Debug::log('Welcome to Luthier-CI ' . LUTHIER_CI_VERSION . '!');
Debug::log('Hello world!','info');
Debug::log('This is a warning, watch out!','warning');
Debug::log('Oh snap! an error was occurred!','error');
$this->load->view('welcome_message');
}
}
```
Y el resultado:
<p align="center">
<img src="https://ingenia.me/uploads/2018/06/19/luthier-ci-debugbar-log.png" alt="Luthier CI PHP Debug Bar" class="img-responsive" />
</p>
Un argumento `$dataCollector` opcional es el nombre del [recolector de datos](http://phpdebugbar.com/docs/data-collectors.html) donde se guardará el mensaje:
```php
Debug::log('Custom data collector','error','my_custom_data_collector');
```
Si necesitas almacenar un mensaje para ser mostrado en la siguiente solicitud (por ejemplo, luego de enviar un formulario) utilza el método `logFlash()`, cuya sintaxis es idéntica al método estático `log()`:
```php
Debug::logFlash('Hey! this will be available in the next request','info');
```
<div class="alert alert-success">
<i class="fa fa-check" aria-hidden="true"></i>
<strong>Desactivado en entornos de producción</strong>
<br />
Si configuras el entorno de tu aplicación a <code>production</code> ésta característica se desactivará automáticamente, y cualquier código de depuración será ignorado
</div>
<div class="alert alert-warning">
<i class="fa fa-warning" aria-hidden="true"></i>
<strong>Requiere que existan datos en el buffer de salida</strong>
<br />
Luthier CI agrega el código de PHP Debug Bar en el buffer de salida ANTES de ser procesado y enviado al navegador por librería <code>output</code> de CodeIgniter. Por lo tanto, es necesario haber utilizado al menos una vez la función <code>$this->load->view()</code> o haber definido explícitamente un buffer de salida sobre el cual trabajar. Las sentencias <code>echo</code> NO producen ningún buffer de salida interno. Además, detener la ejecución del script con las funciones <code>die</code> o <code>exit</code> evitará que se muestre PHP Debug Bar.
</div>
### <a name="add-your-own-data-collectors"></a> Añadir tus propios recolectores de datos
Es posible añadir tus propios recolectores de datos y almacenar mensajes en ellos. Para añadir un recolector de datos a la instancia de PHP Debug Bar, usa el método estático `addCollector()`:
```php
# use Luthier\Debug;
Debug::addCollector(new MyCollector());
```
\ No newline at end of file
[//]: # ([author] Anderson Salas)
[//]: # ([meta_description] ¡Mira en acción a Luthier-CI! aquí recopilamos algunos ejemplos reales de uso para que encuentres inspiración)
# Ejemplos
### Ejemplo #1: Sitio web multi-idioma
En este ejemplo se muestra el manejo de un sitio web multi-idioma a través de la URL.
Utiliza un middleware para cargar el archivo de idioma actual.
```php
<?php
# application/routes/web.php
Route::get('/', function(){
// Ruta "por defecto". Éste es un buen lugar para solicitar una cookie, variable de sesión
// o algo que nos permita restaurar el último idioma del usuario, o bien mostrar una
// pantalla de selección de idioma si no se provee ninguna información.
redirect(route('homepage', ['_locale' => 'en']));
});
Route::group('{((es|en|it|br|ge)):_locale}', ['middleware' => ['Lang_middleware']], function(){
Route::get('home', function(){
var_dump( ci()->lang->line('test') );
})->name('homepage');
Route::get('about', function(){
var_dump( ci()->lang->line('test') );
})->name('about');
});
```
```php
<?php
# application/middleware/Lang_middleware.php
class Lang_middleware
{
public function run()
{
// Obteniendo el valor del parámetro adhesivo "_locale"
$locale = ci()->route->param('_locale');
$langs = [
'es' => 'spanish',
'en' => 'english',
'it' => 'italian',
'br' => 'portuguese-brazilian',
'ge' => 'german',
];
ci()->lang->load('test', $langs[$locale]);
}
}
```
\ No newline at end of file
# About the documentation source files
This is the source of the project [documentation](https://luthier.ingenia.me/ci/en/docs) available in our official website.
<p align="center">
<img src="https://ingenia.me/images/luthier-ci/logo.png" width="100" />
</p>
**Luthier CI** is an awesome set of core improvements for CodeIgniter 3 that makes the development of APIs (and websites in general) more easy!
## Features
* Easy installation via hooks
* Laravel-like routing: prefixes, namespaces, anonymous functions as routes, route groups, CLI routes, named parameters, optional parameters, etc.
* Middleware support
* Authentication library with SimpleAuth template
* PHP Debug Bar integration (experimental)
## Requirements
* PHP >= 5.6.0 (PHP 7 compatible)
* CodeIgniter >= 3.0
## Installation
#### Step 1: Get Luthier CI with Composer
```
composer require luthier/luthier
```
#### Step 2: Enable Hooks and Composer autoload
```php
<?php
# application/config/config.php
$config['enable_hooks'] = TRUE;
$config['composer_autoload'] = TRUE;
```
#### Step 3: Connect Luthier CI with CodeIgniter
Set the hooks:
```php
<?php
# application/config/hooks.php
defined('BASEPATH') OR exit('No direct script access allowed');
// (...)
$hook = Luthier\Hook::getHooks();
```
Set the Luthier CI routes:
```php
<?php
# application/config/routes.php
defined('BASEPATH') OR exit('No direct script access allowed');
// (...)
$route = Luthier\Route::getRoutes();
```
## Initialization
The first time that Luthier CI runs, several files and folders are created:
* `routes/web.php`: Default HTTP-Based routes
* `routes/api.php`: AJAX routes
* `routes/cli.php`: CLI routes
* `controllers/Luthier.php`: Fake controller, necessary to use some routes
* `middleware`: Middleware folder
**Important**: Make sure that your `application` folder has write permission!
## Usage
To add routes, use the static methods of the `Route` class:
```php
<?php
# application/routes/web.php
// This points to 'baz' method of 'bar' controller at '/foo' path under a GET request:
Route::get('foo', 'bar@baz');
// To add a route parameter, enclose with curly brackets {}
Route::get('blog/{slug}', 'blog@post');
// To make a parameter optional, add a ? just before closing the curly brackets
// (Luthier CI will make all the fallback routes for you)
Route::get('categories/{primary?}/{secondary?}/{filter?}', 'clients@list');
// The (:any) and (:num) CodeIgniter route placeholders are available to use, with this syntax:
Route::get('cars/{num:id}/{any:registration}', 'CarCatalog@index');
// Custom regex? it's possible with this syntax:
Route::post('main/{((es|en)):_locale}/about', 'about@index');
```
Use the `Route::cli()` method to add command line routes. All CLI routes must be inside `routes/cli.php` file. This is an example of a CLI route:
```php
Route::cli('path','controller@method');
```
The `ci()` function returns the framework instance, acting as a *virtual* controller. This is useful if you use callbacks as routes:
```php
Route::get('foo', function(){
ci()->load->view('some_view');
});
```
You can assign names to your routes so you don't have to worry about future url changes:
```php
Route::get('company/about_us', 'testcontroller@index')->name('about_us');
```
To retrieve a named route, use the `route()` function:
```php
<a href="<?= route('about_us');?>">My link!</a>
// <a href="http://example.com/company/about_us">Link</a>
```
If the route has parameters, pass a second argument to the function with an array of their values:
```php
<?= route('route_name', ['param1' => 'value2', 'param2' => 'value2' ... ]); ?>
```
#### Route Groups
Group routes is possible with the `Route::group()` method. All routes
inside the group will share the *prefix* (first argument) and, optionally, another property (*namespace*, *middleware*, etc.)
```php
// Prefix only
Route::group('prefix', function(){
Route::get('bar','test@bar');
Route::get('baz','test@baz');
});
// Prefix and shared properties
Route::group('prefix', ['namespace' => 'foo', 'middleware' => ['Admin','IPFilter']], function(){
Route::get('bar','test@bar');
Route::get('baz','test@baz');
});
```
## Middleware
All the middleware must be defined in the routes files (`application/routes/web.php`, `application/routes/api.php`, `application/routes/cli.php`)
```php
# Route middleware:
Route::put('foo/bar','controller@method', ['middleware' => ['Test']]);
# Route group middleware:
Route::group('site', ['middleware' => ['Admin']], function(){
// ...
});
# Global middleware:
Route::middleware('Admin', 'pre_controller');
```
The middleware files must be saved in the `application/middleware` folder. If not exists, you must create it first. A middleware file is any php class that implements the `Luthier\MiddlewareInterface` interface and with a public `run()` method, which is the entry point. It's strongly advised to name all your middleware with CamelCase and avoid name conflicts with your controllers.
This is an example of a middleware:
```php
<?php
# application/middleware/TestMiddleware.php
class TestMiddleware
{
public function run()
{
// (Entry point)
}
}
```
### Documentation
Visit the project [official website](https://luthier.ingenia.me/ci/en/docs) (disponible en [español](https://luthier.ingenia.me/ci/es/docs))
### Related projects
* [Luthier Framework](https://github.com/ingeniasoftware/luthier-framework): Versatile PHP micro-framework for build APIs and websites quickly
* [SimpleDocs](https://github.com/ingeniasoftware/simpledocs): Dynamic documentation library for PHP which uses Markdown files
### Donate
If you love our work, consider support us on [Patreon](https://patreon.com/ingenia)
<?php
/*
* Luthier CI
*
* (c) 2018 Ingenia Software C.A
*
* This file is part of Luthier CI, a plugin for CodeIgniter 3. See the LICENSE
* file for copyright information and license details
*/
namespace Luthier\Auth;
/**
* Describes the methods that must have a controller that authenticates users in
* CodeIgniter applications
*
* @author Anderson Salas <anderson@ingenia.me>
*/
interface ControllerInterface
{
/**
* Gets the User provider used by the Controller-based authentication
*
* @return UserProviderInterface|string
*/
public function getUserProvider();
/**
* Gets the middleware used by the Controller-based authentication
*
* @return \Luthier\Auth\Middleware
*/
public function getMiddleware();
/**
* User login screen
*
* @return mixed
*/
public function login();
/**
* User logout screen
*
* @return mixed
*/
public function logout();
/**
* User sign up screen
*
* @return mixed
*/
public function signup();
/**
* User email verification screen
*
* @param string $token Verification token
*
* @return mixed
*/
public function emailVerification($token);
/**
* User password reset screen
*
* @return mixed
*/
public function passwordReset();
/**
* User password reset form screem
*
* @param string $token Password reset token
*
* @return mixed
*/
public function passwordResetForm($token);
}
<?php
/*
* Luthier CI
*
* (c) 2018 Ingenia Software C.A
*
* This file is part of Luthier CI, a plugin for CodeIgniter 3. See the LICENSE
* file for copyright information and license details
*/
namespace Luthier\Auth;
use Luthier\Auth\Middleware as AuthMiddlewareInterface;
use Luthier\Auth;
use Luthier\Middleware;
use Luthier\MiddlewareInterface;
/**
* Internal middleware that dispatches the Controller-based authentication
* when the ControllerInterface is detected in the framework singleton base object
*
* @author Anderson Salas <anderson@ingenia.me>
*/
class Dispatcher implements MiddlewareInterface
{
/**
* {@inheritDoc}
*
* @see \Luthier\MiddlewareInterface::run()
*/
public function run($args)
{
if(!ci() instanceof ControllerInterface)
{
return;
}
$authMiddleware = ci()->getMiddleware();
if(is_string($authMiddleware))
{
$authMiddleware = Middleware::load($authMiddleware);
}
if(!$authMiddleware instanceof AuthMiddlewareInterface)
{
show_error('The auth middleware must inherit the Luthier\Auth\Middleware class');
}
ci()->middleware->run($authMiddleware, Auth::loadUserProvider(ci()->getUserProvider()));
}
}
\ No newline at end of file
<?php
/*
* Luthier CI
*
* (c) 2018 Ingenia Software C.A
*
* This file is part of Luthier CI, a plugin for CodeIgniter 3. See the LICENSE
* file for copyright information and license details
*/
namespace Luthier\Auth\Exception;
/**
* Exception thrown by an User provider when an inactive user attempts to log in
*
* @author Anderson Salas <anderson@ingenia.me>
*/
class InactiveUserException extends \Exception
{
};
\ No newline at end of file
<?php
/*
* Luthier CI
*
* (c) 2018 Ingenia Software C.A
*
* This file is part of Luthier CI, a plugin for CodeIgniter 3. See the LICENSE
* file for copyright information and license details
*/
namespace Luthier\Auth\Exception;
/**
* Exception thrown when a non existing ACL permission is requested
*
* @author Anderson Salas <anderson@ingenia.me>
*/
class PermissionNotFoundException extends \Exception
{
};
\ No newline at end of file
<?php
/*
* Luthier CI
*
* (c) 2018 Ingenia Software C.A
*
* This file is part of Luthier CI, a plugin for CodeIgniter 3. See the LICENSE
* file for copyright information and license details
*/
namespace Luthier\Auth\Exception;
/**
* Exception thrown by an User provider when an unverified user attempts to log in
*
* @author Anderson Salas <anderson@ingenia.me>
*/
class UnverifiedUserException extends \Exception
{
};
\ No newline at end of file
<?php
/*
* Luthier CI
*
* (c) 2018 Ingenia Software C.A
*
* This file is part of Luthier CI, a plugin for CodeIgniter 3. See the LICENSE
* file for copyright information and license details
*/
namespace Luthier\Auth\Exception;
/**
* Exception thrown by an User provider when an user can't be founded
*
* @author Anderson Salas <anderson@ingenia.me>
*/
class UserNotFoundException extends \Exception
{
};
\ No newline at end of file
<?php
/*
* Luthier CI
*
* (c) 2018 Ingenia Software C.A
*
* This file is part of Luthier CI, a plugin for CodeIgniter 3. See the LICENSE
* file for copyright information and license details
*/
namespace Luthier\Auth;
use Luthier\Auth;
use Luthier\Middleware as LuthierMiddleware;
use Luthier\MiddlewareInterface;
use Luthier\Auth\Exception\UserNotFoundException;
use Luthier\Auth\Exception\InactiveUserException;
use Luthier\Auth\Exception\UnverifiedUserException;
use Luthier\Route;
use Luthier\Debug;
/**
* Controller-based authentication middleware
*
* This is a special middleware used internally by Luthier CI. Handles
* the Controller-based authentication and dispatches special authentication
* events during the process.
*
* @author AndersonRafael
*/
abstract class Middleware implements MiddlewareInterface
{
/**
* {@inheritDoc}
*
* @see \Luthier\MiddlewareInterface::run()
*/
final public function run($userProvider)
{
Debug::log(
'>>> USING CONTROLLER-BASED AUTH ['
. get_class(ci()) . ', '
. get_class($userProvider) . ', '
. get_class( is_object(ci()->getMiddleware()) ? ci()->getMiddleware() : LuthierMiddleware::load(ci()->getMiddleware()) ) . ' ]',
'info', 'auth');
$authLoginRoute = config_item('auth_login_route') !== null
? config_item('auth_login_route')
: 'login';
$authLoginRouteRedirect = config_item('auth_login_route_redirect') !== null
? config_item('auth_login_route_redirect')
: null;
$authLogoutRoute = config_item('auth_logout_route') !== null
? config_item('auth_logout_route')
: 'logout';
$authLogoutRouteRedirect = config_item('auth_logout_route_redirect') !== null
? config_item('auth_logout_route_redirect')
: null;
$authRouteAutoRedirect = is_array( config_item('auth_route_auto_redirect') )
? config_item('auth_route_auto_redirect')
: [];
if( !Auth::isGuest() && ( ci()->route->getName() == $authLoginRoute || in_array(ci()->route->getName(), $authRouteAutoRedirect)) )
{
return redirect(
$authLoginRouteRedirect !== null && route_exists($authLoginRouteRedirect)
? route($authLoginRouteRedirect)
: base_url()
);
}
$this->preLogin(ci()->route);
if(ci()->route->getName() == $authLoginRoute && ci()->route->requestMethod == 'POST')
{
$usernameField = config_item('auth_form_username_field') !== null
? config_item('auth_form_username_field')
: 'username';
$passwordField = config_item('auth_form_password_field') !== null
? config_item('auth_form_password_field')
: 'password';
$username = ci()->input->post($usernameField);
$password = ci()->input->post($passwordField);
Debug::logFlash('>>> LOGIN ATTEMPT INTERCEPTED', 'info', 'auth');
Debug::logFlash('Username: ' . $username, 'info', 'auth');
Debug::logFlash('Password: ' . $password . ' [hash: ' . $userProvider->hashPassword($password) . ']', 'info', 'auth');
try
{
$user = $userProvider->loadUserByUsername($username, $password);
$userProvider->checkUserIsActive($user);
$userProvider->checkUserIsVerified($user);
}
catch(UserNotFoundException $e)
{
Debug::logFlash('FAILED: ' . UserNotFoundException::class, 'error', 'auth');
ci()->session->set_flashdata('_auth_messages', [ 'danger' => 'ERR_LOGIN_INVALID_CREDENTIALS' ]);
$this->onLoginFailed($username);
return redirect(route($authLoginRoute));
}
catch(InactiveUserException $e)
{
Debug::logFlash('FAILED: ' . InactiveUserException::class, 'error', 'auth');
ci()->session->set_flashdata('_auth_messages', [ 'danger' => 'ERR_LOGIN_INACTIVE_USER' ]);
$this->onLoginInactiveUser($user);
return redirect(route($authLoginRoute));
}
catch(UnverifiedUserException $e)
{
Debug::logFlash('FAILED: ' . UnverifiedUserException::class, 'error', 'auth');
ci()->session->set_flashdata('_auth_messages', [ 'danger' => 'ERR_LOGIN_UNVERIFIED_USER' ]);
$this->onLoginUnverifiedUser($user);
return redirect(route($authLoginRoute));
}
Auth::store($user);
$this->onLoginSuccess($user);
return redirect( $authLoginRouteRedirect !== null ? route($authLoginRouteRedirect) : base_url() );
}
if(ci()->route->getName() == $authLogoutRoute)
{
Auth::destroy();
$this->onLogout();
return redirect(
$authLogoutRouteRedirect !== null && route_exists($authLogoutRouteRedirect)
? route($authLogoutRouteRedirect)
: base_url()
);
}
}
/**
* Event triggered when the user visits the login path, regardless of whether
* logs in or not
*
* @param Route $route Current route
*
* @return void
*/
abstract public function preLogin(Route $route);
/**
* Event triggered immediately after a successful login session, and before the
* redirect that follows
*
* @param UserInterface $user Current user
*
* @return void
*/
abstract public function onLoginSuccess(UserInterface $user);
/**
* Event triggered after a failed session attempt, and before the redirect that
* follows
*
* @param string $username Attempted username
*
* @return void
*/
abstract public function onLoginFailed($username);
/**
* Event triggered if an InactiveUserException exception is thrown within the
* User Provider, corresponding to an inactive user login error
*
* @param UserInterface $user
*
* @return void
*/
abstract public function onLoginInactiveUser(UserInterface $user);
/**
* Event triggered if an `UnverifiedUserException` exception is thrown inside the
* User Provider, corresponding to an error by login of an unverified user.
*
* @param UserInterface $user
*
* @return void
*/
abstract public function onLoginUnverifiedUser(UserInterface $user);
/**
* Event triggered immediately after the user log out.
*
* @return void
*/
abstract public function onLogout();
}
\ No newline at end of file
<?php
/*
* Luthier CI
*
* (c) 2018 Ingenia Software C.A
*
* This file is part of Luthier CI, a plugin for CodeIgniter 3. See the LICENSE
* file for copyright information and license details
*/
namespace Luthier\Auth\SimpleAuth;
use Luthier\Auth\Middleware as AuthMiddleware;
use Luthier\Auth\UserInterface;
use Luthier\Auth\SimpleAuth\Middleware\RememberMeMiddleware;
use Luthier\Route;
/**
* SimpleAuth implementation of the Controller-based authentication
*
* @author Anderson Salas <anderson@ingenia.me>
*/
class Middleware extends AuthMiddleware
{
/**
* {@inheritDoc}
*
* @see \Luthier\Auth\Middleware::preLogin()
*/
public function preLogin(Route $route)
{
if(
$route->getName() == config_item('auth_login_route') &&
$route->requestMethod == 'POST' &&
config_item('simpleauth_enable_brute_force_protection') === true
)
{
ci()->load->database();
$loginAttemptCount = ci()->db->where('ip', $_SERVER['REMOTE_ADDR'])
->where('created_at >=', date('Y-m-d H:i:s', time() - (60 * 30)) ) // 30 minutes
->where('created_at <=', date('Y-m-d H:i:s', time()))
->count_all_results(config_item('simpleauth_login_attempts_table'));
if($loginAttemptCount >= 4)
{
ci()->session->set_flashdata('_auth_messages', [ 'danger' => 'ERR_LOGIN_ATTEMPT_BLOCKED' ]);
return redirect(route(config_item('auth_login_route')));
}
}
}
/**
* {@inheritDoc}
*
* @see \Luthier\Auth\Middleware::onLoginSuccess()
*/
public function onLoginSuccess(UserInterface $user)
{
if( config_item('simpleauth_enable_remember_me') === true )
{
ci()->middleware->run( new RememberMeMiddleware(), 'store');
}
return redirect(
route_exists(config_item('auth_login_route_redirect'))
? route(config_item('auth_login_route_redirect'))
: base_url()
);
}
/**
* {@inheritDoc}
*
* @see \Luthier\Auth\Middleware::onLoginFailed()
*/
public function onLoginFailed($username)
{
ci()->load->database();
if( config_item('simpleauth_enable_brute_force_protection') === true )
{
ci()->db->insert(
config_item('simpleauth_login_attempts_table'),
[
'username' => $username,
'ip' => $_SERVER['REMOTE_ADDR']
]
);
}
}
/**
* {@inheritDoc}
*
* @see \Luthier\Auth\Middleware::onLoginInactiveUser()
*/
public function onLoginInactiveUser(UserInterface $user)
{
return;
}
/**
* {@inheritDoc}
*
* @see \Luthier\Auth\Middleware::onLoginUnverifiedUser()
*/
public function onLoginUnverifiedUser(UserInterface $user)
{
return;
}
/**
* {@inheritDoc}
*
* @see \Luthier\Auth\Middleware::onLogout()
*/
public function onLogout()
{
ci()->middleware->run( new RememberMeMiddleware(), 'destroy');
}
}
\ No newline at end of file
<?php
/*
* Luthier CI
*
* (c) 2018 Ingenia Software C.A
*
* This file is part of Luthier CI, a plugin for CodeIgniter 3. See the LICENSE
* file for copyright information and license details
*/
namespace Luthier\Auth\SimpleAuth\Middleware;
use Luthier\MiddlewareInterface;
use Luthier\Auth;
/**
* Special 'Remember me' feature of SimpleAuth
*
* @author Anderson Salas <anderson@ingenia.me>
*/
class RememberMeMiddleware implements MiddlewareInterface
{
/**
* {@inheritDoc}
*
* @see \Luthier\MiddlewareInterface::run()
*/
public function run($action = 'store')
{
if($action == 'store')
{
$this->storeAuthCookie();
}
elseif($action == 'restore')
{
$this->restoreAuthFromCookie();
}
elseif($action == 'destroy')
{
$this->destroyAuthCookie();
}
else
{
show_error('Unknown RememberMeMiddleware "' . $action . '" action');
}
}
private function storeAuthCookie()
{
if(ci()->input->post(config_item('simpleauth_remember_me_field')) === null)
{
return;
}
ci()->load->library('encryption');
$rememberToken = bin2hex(ci()->encryption->create_key(32));
ci()->db->update(
config_item('simpleauth_users_table'),
[config_item('simpleauth_remember_me_col') => $rememberToken],
['id' => Auth::user()->id]
);
ci()->input->set_cookie(config_item('simpleauth_remember_me_cookie'), $rememberToken, 1296000); // 15 days
}
private function restoreAuthFromCookie()
{
if( !Auth::isGuest() || Auth::session('fully_authenticated') === true)
{
return;
}
ci()->load->database();
ci()->load->helper('cookie');
ci()->load->library('encryption');
$rememberToken = get_cookie(config_item('simpleauth_remember_me_cookie'));
if( empty($rememberToken) )
{
return;
}
$storedUserFromToken = ci()->db->get_where(
config_item('simpleauth_users_table'),
[config_item('simpleauth_remember_me_col') => $rememberToken]
)->result();
if(empty($storedUserFromToken))
{
delete_cookie(config_item('simpleauth_remember_me_cookie'));
return;
}
$userProvider = Auth::loadUserProvider(config_item('simpleauth_user_provider'));
try
{
$user = Auth::bypass($storedUserFromToken[0]->{config_item('simpleauth_username_col')}, $userProvider);
$userProvider->checkUserIsActive($user);
if(
config_item('simpleauth_enable_email_verification') === TRUE &&
config_item('simpleauth_enforce_email_verification') === TRUE
)
{
$userProvider->checkUserIsVerified($user);
}
}
catch(\Exception $e)
{
delete_cookie(config_item('simpleauth_remember_me_cookie'));
return;
}
Auth::store($user, ['fully_authenticated' => false]);
}
private function destroyAuthCookie()
{
ci()->load->helper('cookie');
delete_cookie(config_item('simpleauth_remember_me_cookie'));
}
}
\ No newline at end of file
<?php
/*
* Luthier CI
*
* (c) 2018 Ingenia Software C.A
*
* This file is part of Luthier CI, a plugin for CodeIgniter 3. See the LICENSE
* file for copyright information and license details
*/
namespace Luthier\Auth\SimpleAuth\Middleware;
use Luthier\Auth;
use Luthier\MiddlewareInterface;
use Luthier\Auth\ControllerInterface as AuthControllerInterface;
/**
* Basic security layer for routing that requires user authentication.
*
* @author Anderson Salas <anderson@ingenia.me>
*/
class SimpleAuthMiddleware implements MiddlewareInterface
{
/**
* {@inheritDoc}
*
* @see \Luthier\MiddlewareInterface::run()
*/
public function run($args)
{
if(ci() instanceof AuthControllerInterface)
{
return;
}
if( config_item('simpleauth_enable_remember_me') === true )
{
ci()->middleware->run(new RememberMeMiddleware(), 'restore');
}
if( Auth::isGuest() )
{
if(ci()->route->getName() != config_item('auth_login_route'))
{
redirect( route(config_item('auth_login_route')) );
exit;
}
}
}
}
\ No newline at end of file
<?php
/*
* Luthier CI
*
* (c) 2018 Ingenia Software C.A
*
* This file is part of Luthier CI, a plugin for CodeIgniter 3. See the LICENSE
* file for copyright information and license details
*/
namespace Luthier\Auth\SimpleAuth;
use Luthier\Auth\UserInterface;
/**
* SimpleAuth User class
*
* @author Anderson Salas <anderson@ingenia.me>
*/
class User implements UserInterface
{
/**
* @var object
*/
private $user;
/**
* @var array
*/
private $roles;
/**
* @var array
*/
private $permissions;
/**
* @param object $entity
* @param array $roles
* @param array $permissions
*/
public function __construct($entity, $roles, $permissions)
{
$this->user = $entity;
$this->roles = $roles;
$this->permissions = $permissions;
}
public function __get($name)
{
if(isset($this->getEntity()->{$name}))
{
return $this->getEntity()->{$name};
}
}
public function getEntity()
{
return $this->user;
}
public function getUsername()
{
return $this->user->email;
}
public function getRoles()
{
return $this->roles;
}
public function getPermissions()
{
return $this->permissions;
}
}
\ No newline at end of file
<?php
/*
* Luthier CI
*
* (c) 2018 Ingenia Software C.A
*
* This file is part of Luthier CI, a plugin for CodeIgniter 3. See the LICENSE
* file for copyright information and license details
*/
namespace Luthier\Auth\SimpleAuth;
use Luthier\Auth\UserInterface;
use Luthier\Auth\UserProviderInterface;
use Luthier\Auth\Exception\UserNotFoundException;
use Luthier\Auth\Exception\InactiveUserException;
use Luthier\Auth\Exception\UnverifiedUserException;
/**
* SimpleAuth user provider
*
* @author Anderson Salas <anderson@ingenia.me>
*/
class UserProvider implements UserProviderInterface
{
/**
* {@inheritDoc}
*
* @see \Luthier\Auth\UserProviderInterface::getUserClass()
*/
public function getUserClass()
{
return 'User';
}
/**
* {@inheritDoc}
*
* @see \Luthier\Auth\UserProviderInterface::loadUserByUsername()
*/
final public function loadUserByUsername($username, $password = null)
{
ci()->load->database();
$user = ci()->db->get_where(
config_item('simpleauth_users_table'),
[ config_item('simpleauth_username_col') => $username ]
)->result();
if(empty($user) || ($password !== null && !$this->verifyPassword($password, $user[0]->{config_item('simpleauth_password_col')})))
{
throw new UserNotFoundException();
}
$userClass = $this->getUserClass();
$roles = [ $user[0]->{config_item('simpleauth_role_col')} ];
$permissions = [];
if(config_item('simpleauth_enable_acl') === true)
{
$databaseUserPermissions = ci()->db->get_where(
config_item('simpleauth_users_acl_table'),
[ 'user_id' => $user[0]->id ]
)->result();
if(!empty($databaseUserPermissions))
{
foreach($databaseUserPermissions as $permission)
{
$permissionName = '';
Library::walkUpPermission($permission->category_id, $permissionName);
$permissions[$permission->category_id] = $permissionName;
}
}
}
return new $userClass($user[0], $roles, $permissions);
}
/**
* {@inheritDoc}
*
* @see \Luthier\Auth\UserProviderInterface::checkUserIsActive()
*/
final public function checkUserIsActive(UserInterface $user)
{
if($user->getEntity()->{config_item('simpleauth_active_col')} == 0)
{
throw new InactiveUserException();
}
}
/**
* {@inheritDoc}
*
* @see \Luthier\Auth\UserProviderInterface::checkUserIsVerified()
*/
final public function checkUserIsVerified(UserInterface $user)
{
$enableCheck = config_item('simpleauth_enable_email_verification') === TRUE &&
config_item('simpleauth_enforce_email_verification') === TRUE;
if(!$enableCheck)
{
return;
}
if($user->getEntity()->{config_item('simpleauth_verified_col')} == 0)
{
throw new UnverifiedUserException();
}
}
/**
* {@inheritDoc}
*
* @see \Luthier\Auth\UserProviderInterface::hashPassword()
*/
public function hashPassword($password)
{
return password_hash($password, PASSWORD_DEFAULT);
}
/**
* {@inheritDoc}
*
* @see \Luthier\Auth\UserProviderInterface::verifyPassword()
*/
public function verifyPassword($password, $hash)
{
return password_verify($password, $hash);
}
}
\ No newline at end of file
<?php
/*
* Luthier CI
*
* (c) 2018 Ingenia Software C.A
*
* This file is part of Luthier CI, a plugin for CodeIgniter 3. See the LICENSE
* file for copyright information and license details
*/
namespace Luthier\Auth;
/**
* Describes which methods must implement all the classes used as a representation
* of an authenticated user in CodeIgniter
*
* @author Anderson Salas <anderson@ingenia.me>
*/
interface UserInterface
{
/**
* @param mixed $entity User data entity, usually an object
* @param array $roles User roles
* @param array $permissions User permissions
*/
public function __construct($entity, $roles, $permissions);
/**
* Gets the user entity
*
* @return mixed
*/
public function getEntity();
/**
* Gets the username from the user entity
*
* @return string
*/
public function getUsername();
/**
* Gets the user roles
*
* @return array
*/
public function getRoles();
/**
* Gets the user permissions
*
* @return array
*/
public function getPermissions();
}
<?php
/*
* Luthier CI
*
* (c) 2018 Ingenia Software C.A
*
* This file is part of Luthier CI, a plugin for CodeIgniter 3. See the LICENSE
* file for copyright information and license details
*/
namespace Luthier\Auth;
/**
* Describes which methods must implement the classes that retrieves
* authenticated users for the application
*
* @author Anderson Salas <anderson@ingenia.me>
*/
interface UserProviderInterface
{
/**
* Gets the related User class name used by this User Provider
*/
public function getUserClass();
/**
* Attemps to load an user from somewhere with the given username and
* password
*
* @param string $username
* @param string|null $password
*
* @return mixed
*/
public function loadUserByUsername($username, $password = null);
/**
* Hashes the given plain text password with an encryption algorithm
*
* @param string $password
*
* @throws \Luthier\Auth\Exception\UnverifiedUserException
*/
public function hashPassword($password);
/**
* Verifies that the given (plain text) password matches with
* the given password hash
*
* @param string $password
* @param string $hash
*
* @return bool
*/
public function verifyPassword($password, $hash);
/**
* Checks if the current user is active
*
* @param UserInterface $user
*
* @throws \Luthier\Auth\Exception\InactiveUserException
*
* @return void
*/
public function checkUserIsActive(UserInterface $user);
/**
* Checks if the current user is verified
*
* @param UserInterface $user
*
* @throws \Luthier\Auth\Exception\UnverifiedUserException
*
* @return void
*/
public function checkUserIsVerified(UserInterface $user);
}
\ No newline at end of file
<?php
/*
* Luthier CI
*
* (c) 2018 Ingenia Software C.A
*
* This file is part of Luthier CI, a plugin for CodeIgniter 3. See the LICENSE
* file for copyright information and license details
*/
namespace Luthier;
use DebugBar\StandardDebugBar as DebugBar;
/**
* Wrapper of PHP Debug integration for Luthier CI
*
* @author Anderson Salas <anderson@ingenia.me>
*/
class Debug
{
/**
* @var \DebugBar\StandardDebugBar
*/
private static $debugBar;
/**
* Creates an instance of PHP DebugBar
*
* @return void
*/
public static function init()
{
if(ENVIRONMENT == 'production')
{
return;
}
self::$debugBar = new DebugBar();
self::setDebugBarRoutes();
}
/**
* Gets the current PHP Debug Bar instance
*
* @return \DebugBar\StandardDebugBar
*/
public static function getDebugBar()
{
return self::$debugBar;
}
/**
* Sets PHP Debug Bar assets routes
*
* @return void
*/
private static function setDebugBarRoutes()
{
RouteBuilder::any('_debug_bar/css', function(){
ob_start();
Debug::getDebugBar()->getJavascriptRenderer()->dumpCssAssets();
// CSS tweaks
echo "
div.phpdebugbar-header, a.phpdebugbar-restore-btn
{
background-color: white;
background-position-y: 6px;
}
a.phpdebugbar-restore-btn
{
height: 21px;
}
div.phpdebugbar-header > div > *
{
padding: 8px 8px;
}
div.phpdebugbar-resize-handle
{
border-bottom: 2px solid black;
}
a.phpdebugbar-minimize-btn, a.phpdebugbar-close-btn, a.phpdebugbar-maximize-btn
{
margin: 3px 0px 0px 5px;
padding-bottom: 0px !important;
}
div.phpdebugbar-minimized
{
border-top: 2px solid black;
}
a.phpdebugbar-tab span.phpdebugbar-badge
{
background: white;
color: #ff5722;
font-weight: bold;
font-size: 12px;
vertical-align: unset;
border-radius: 42%;
padding: 2px 7px;
}
a.phpdebugbar-tab.phpdebugbar-active
{
background-image: none;
background: #FF5722;
color: white !important;
}
div.phpdebugbar-mini-design a.phpdebugbar-tab
{
border-right: none;
min-height: 16px;
}
";
$css = ob_get_clean();
$css = str_ireplace("url('../fonts/fontawesome-webfont", "url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/fonts/fontawesome-webfont", $css);
ci()->output
->set_content_type('text/css')
->set_output($css)
->_display();
exit;
})->name('debug_bar.css_assets');
RouteBuilder::any('_debug_bar/js', function(){
ob_start();
Debug::getDebugBar()->getJavascriptRenderer()->dumpJsAssets();
$js = ob_get_clean();
ci()->output
->set_content_type('text/javascript')
->set_output($js)
->_display();
exit;
})->name('debug_bar.js_assets');
}
/**
* Injects the PHP Debug Bar required assets to the HTML output returned by the
* CI_Output::get_output() method
*
* @param mixed $output
*
* @return void
*/
public static function prepareOutput(&$output)
{
if(ENVIRONMENT != 'production' && !ci()->input->is_ajax_request() && !is_cli() && self::$debugBar !== null)
{
$head = "<script>
function asset_retry(node, type)
{
if(type == 'css')
{
node.href = node.href + '?retry=' + (Math.random() * 100);
}
else
{
node.src = node.href + '?retry=' + (Math.random() * 100);
}
phpdebugbar.restoreState();
}
</script>" ;
$head .= '<link rel="stylesheet" href="'. route('debug_bar.css_assets') .'" onerror="asset_retry(this, \'css\')" />';
$body = '<script src="'. route('debug_bar.js_assets') .'" onerror="asset_retry(this, \'js\')"></script>';
$body .= Debug::getDebugBar()->getJavascriptRenderer()->render();
$output = str_ireplace('</head>', $head . '</head>', $output);
$output = str_ireplace('</body>', $body . '</body>', $output);
}
}
/**
* Logs a message in a PHP Debug Bar data collector
*
* @param string $message Content
* @param string $type Type
* @param string $collector Collector name ('messages' by default)
*/
public static function log($message, $type = 'info', $collector = 'messages')
{
if(ENVIRONMENT == 'production' || self::$debugBar === null)
{
return;
}
if($message instanceof \Exception)
{
self::getDebugBar()->getCollector('exceptions')->addException($message);
return;
}
self::getDebugBar()->getCollector($collector)->addMessage($message, $type, is_string($message));
}
/**
* Logs a message that will be available in the next request
* as a session flash variable
*
* @param string $message Content
* @param string $type Type
* @param string $collector Collector name ('messages' by default)
*/
public static function logFlash($message, $type = 'info', $collector = 'messages')
{
if(ENVIRONMENT == 'production' || self::$debugBar === null)
{
return;
}
$messages = ci()->session->flashdata('_debug_bar_flash');
$messages[] = [ $message, $type, $collector ];
ci()->session->set_flashdata('_debug_bar_flash', $messages);
}
/**
* Add a Data Collector to the current PHP DebugBar instance
*
* @param mixed $dataCollector
*
* @return mixed
*
* @access public
* @static
*/
/**
* Adds a data collector to the PHP Debug Bar instance
*
* @param \DebugBar\DataCollector\DataCollectorInterface $dataCollector
*
* @return void
*/
public static function addCollector($dataCollector)
{
if(ENVIRONMENT == 'production' || self::$debugBar === null)
{
return;
}
self::getDebugBar()->addCollector($dataCollector);
}
}
\ No newline at end of file
<?php
/*
* Luthier CI
*
* (c) 2018 Ingenia Software C.A
*
* This file is part of Luthier CI, a plugin for CodeIgniter 3. See the LICENSE
* file for copyright information and license details
*/
namespace Luthier\Exception;
/**
* Exception thrown when a non existing route is requested
*
* @author Anderson Salas <anderson@ingenia.me>
*/
class RouteNotFoundException extends \Exception
{
}
\ No newline at end of file
<?php
/*
* Luthier CI
*
* (c) 2018 Ingenia Software C.A
*
* This file is part of Luthier CI, a plugin for CodeIgniter 3. See the LICENSE
* file for copyright information and license details
*/
/**
* Luthier CI Authentication global class alias
*
* @author AndersonRafael
*/
class Auth extends Luthier\Auth
{
}
\ No newline at end of file
<?php
/*
* Luthier CI
*
* (c) 2018 Ingenia Software C.A
*
* This file is part of Luthier CI, a plugin for CodeIgniter 3. See the LICENSE
* file for copyright information and license details
*/
/**
* Luthier CI Route global class alias
*
* @author <anderson@ingenia.me>
*/
class Route extends Luthier\RouteBuilder
{
}
<?php
/*
* Luthier CI
*
* (c) 2018 Ingenia Software C.A
*
* This file is part of Luthier CI, a plugin for CodeIgniter 3. See the LICENSE
* file for copyright information and license details
*/
/**
* Gets a route URL by its name
*
* @param string $name Route name
* @param array $params Route parameters
*
* @return string
*/
function route($name = null, $params = [])
{
if($name === null)
{
$route = Route::getCurrentRoute();
}
else
{
$route = Route::getByName($name);
}
return $route->buildUrl($params);
}
/**
* Checks if a route exists
*
* @param string $name Route name
*
* @return bool
*/
function route_exists($name)
{
return isset(Route::$compiled['names'][$name]);
}
/**
* Returns the framework singleton
*
* (Alias of &get_instance() CodeIgniter function)
*
* @return object
*/
function &ci()
{
return get_instance();
}
/**
* Shows a screen with information about Luthier CI
*
* @return void
*/
function luthier_info()
{
ob_start();
require LUTHIER_CI_DIR . '/Resources/About.php';
$luthierInfo = ob_get_clean();
ci()->output->set_output($luthierInfo);
}
/**
* Triggers the custom Luthier CI 404 error page, with fallback to
* native show_404() function
*
* @return void
*/
function trigger_404()
{
$_404 = Route::get404();
if(is_null($_404) || !is_callable($_404))
{
show_404();
}
call_user_func($_404);
exit;
}
/**
* Redirects to a route URL by its name
*
* @param string $name Route name
* @param array $params Route parameters
* @param array $messages Array with flashdata messages
*
* @return void
*/
function route_redirect($name, $params = [], $messages = [])
{
if(!empty($messages) && is_array($messages))
{
ci()->load->library('session');
foreach($messages as $_name => $_value)
{
ci()->session->set_flashdata($_name, $_value);
}
}
redirect(route($name, $params));
}
\ No newline at end of file
<?php
/*
* Luthier CI
*
* (c) 2018 Ingenia Software C.A
*
* This file is part of Luthier CI, a plugin for CodeIgniter 3. See the LICENSE
* file for copyright information and license details
*/
namespace Luthier;
/**
* Middleware handler class
*
* @author Anderson Salas <anderson@ingenia.me>
*/
class Middleware
{
/**
* @var array
*/
private static $loadedMiddleware = [];
/**
* Loads a middleware class
*
* @param mixed $middleware Middleware name
*
* @return void
*/
public static function load($middleware)
{
# START CUSTOM PASSING PARAMETER FROM ROUTE
$split = explode(":",$middleware);
$params = $split[1];
$middleware = $split[0];
# END CUSTOM PASSING PARAMETER FROM ROUTE
if(isset(self::$loadedMiddleware[$middleware]))
{
return self::$loadedMiddleware[$middleware];
}
$target = APPPATH . '/middleware/' . $middleware . '.php';
if( file_exists($target))
{
require_once($target);
$middlewareInstance = new $middleware();
if(!$middlewareInstance instanceof MiddlewareInterface)
{
show_error('Your middleware MUST implement the "MiddlewareInterface" interface');
}
self::$loadedMiddleware[$middleware] = $middlewareInstance;
return call_user_func([$middlewareInstance, 'run'], $params); # CUSTOM PASSING PARAMETER TO MIDDLEWARE
// return $middlewareInstance; # ORIGINAL
}
show_error('Unable to find <strong>' . $middleware .'.php</strong> in your application/middleware folder');
}
/**
* Runs a middleware
*
* @param string|callable $middleware
* @param array $args
*
* @return void
*/
final public function run($middleware, $args = [])
{
if(is_callable($middleware))
{
call_user_func_array($middleware, $args);
}
// else if(is_object($middleware) && $middleware instanceof MiddlewareInterface)
else if(is_object($middleware))
{
if(!$middleware instanceof MiddlewareInterface)
{
Debug::log('DEPRECATED: All your middleware MUST implement the Luthire\MiddlewareInterface interface. Please fix this issue with "' . get_class($middleware) . '" middleware');
if(method_exists($middleware,'run'))
{
show_error('Your "' . get_class($middleware) . '" middleware doesn\'t have a run() public method');
}
}
$middleware->run($args);
}
else if(is_array($middleware))
{
foreach($middleware as $run)
{
$this->run($run, $args);
}
return;
}
else
{
$middlewareInstance = self::load($middleware);
call_user_func([$middlewareInstance, 'run'], $args);
}
}
/**
* Binds a middleware to CodeIgniter hook at runtime
*
* @param string $hook Hook name
* @param callable $middleware Middleware callable
* @param array[] ...$args Middleware ars
*
* @return void
*/
final public function addHook($hook, $middleware, ...$args)
{
if(is_callable($middleware))
{
if(empty($args))
{
$args[] =& get_instance();
}
if(isset(ci()->hooks->hooks[$hook]) && !is_array(ci()->hooks->hooks[$hook]))
{
$_hook = ci()->hooks->hooks[$hook];
ci()->hooks->hooks[$hook] = [ $_hook ];
}
ci()->hooks->hooks[$hook][] = call_user_func_array($middleware, $args);
}
else
{
ci()->hooks->hooks[$hook][] = call_user_function_array([$this,'run'], [ $middleware, $args] );
}
}
}
<?php
/*
* Luthier CI
*
* (c) 2018 Ingenia Software C.A
*
* This file is part of Luthier CI, a plugin for CodeIgniter 3. See the LICENSE
* file for copyright information and license details
*/
namespace Luthier;
/**
* All Luthier CI middleware used in the application SHOULD implement this interface,
* in order to be properly detected by the router
*
* @author Anderson Salas <anderson@ingenia.me>
*/
interface MiddlewareInterface
{
/**
* Middleware entry point
*
* @param mixed $args Middleware arguments
*
* @return mixed
*/
public function run($args);
}
\ No newline at end of file
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Welcome to Luthier CI!</title>
<link href="http://fonts.googleapis.com/css?family=Open+Sans:300,regular" rel="stylesheet" type="text/css">
<style>
body
{
background: white;
margin: 0;
padding: 0;
font-family: "Open Sans", "Arial", "Helvetica", sans-serif
}
h1
{
font-weight: 300;
font-size: 50px;
margin: 0;
}
.container
{
padding-top: 100px;
text-align: center;
display: block;
margin: 0px auto;
}
.version
{
color: silver;
}
a
{
text-decoration: none;
color: #ed6113;
}
a:hover, a:focus
{
text-decoration: underline;
color: #D15310;
}
</style>
</head>
<body>
<div class="container">
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAMAAABHPGVmAAAABGdBTUEAALGPC/xhBQAAAwBQTFRF7WET7WEU7WIU7WIV7WMW7WMX7WQX7WQY7WUZ7mYa7mYb7mcc7mgd7mkf7mog7moh7msi7msj7mwj7m0l7m4m7m4n728o73Ap73Aq73Er73Es73Is73Mt73Qv73Ux73Yz73c08Hc08Hg18Hk28Hk38Ho48Hs68Hw78Hw88H098H4/8H9A8YBB8YBC8YFD8YJE8YNG8YNH8YRH8YVJ8YZK8YZL8YdM8YhN8YlO8olP8opQ8otS8oxU8o1V8o5W8o5X8o9Y8pBZ8pBa85Fb8pJc85Ne85Rf85Rg85Zi85Zj85dk85hl85lm85ln9Jpn9Jpo9Jtp9Jtq9Jxr9J1s9J1t9J5t9J5u9J9v9J9w9KBy9KJ09KJ19aN29aR29aR39aR49aZ79ad89ah99al+9ap/9aqA9aqB9qyD9q2E9q2F9q+H9rCJ9rGK9rGL9rKN9rSO97WQ97eT97iU97iV97mW97mX97qY97ya97yb+L6e+L+f+MCh+MCi+MGj+MKk+MOm+MSn+MWo+MWp+Maq+cit+cmu+cqw+c20+c21+c61+c63+s+4+tC4+tG6+tS/+tXA+tbC+tfD+tfE+9jE+9vJ+9zK+9zL+93M+93N+97N+9/P++DQ++DR/OLU/OPW/OTW/OXY/Ofb/Ojc/Ojd/One/enf/erg/evh/e3k/e/n/e/o/fDo/fDp/fHq/vLs/vPt/vTu/vTv/vXw/vXx/vbx/vby/vfz/vj0/vn1/vn2/vr3/vr4//v6//z6//z7//38//79//7+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAw8hhIQAAAAlwSFlzAAAOwQAADsEBuJFr7QAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4xNzNun2MAAAQ+SURBVGhD7dlpdxRFFIfxIWDYxIgogiKIoAEkgMaogJoEUcQdNzYlMWpUVASBgGsQMRpBQVDZVESQRQgQDOCAkHR9Mmeqnma6q2uOTs3tNx5/b5i69577PyfTw5npzuRNVnm9w/UhLTU6pO8Gjumo1SHBeI7pmG1CqjmmY64OUXdyTMcjJmQWx3Q8bUIaOKZjsQmZxzEdzSbkGY7peN2ELOGYjndMyMsc0/GeCXmTYzreNyHvckxHuwlZy1He0LtaO06akOObWmYMoSzrrAkI/fFZfSUdQSyPOLx0ED0xbI7Zfw9NKeyN622toC2DtbaVtGWw1BYspC+CpQlnb2JAAjuT2hmQwMqk7AgmBLDS4XkmBLDRYSMTAtjo8CMTAtjo0MWEADY6ZJkQwEaH80wIYKNDNxMC2OhwgAkBbHT4lgkBbHT4kAkBbHR4kQkBbEwKapgQwMqkM4JfXFiZ9A0DEliZ9AoDEliZNIcBCaxMWmb6IliZtJkBCay0BbvS/3Ptv5e2DLbG7ayiK4S1Md2jaUphb8xb9MSwNyq4hZ4YFkcJfoMAi6P20pLD4qjdtOSwOOoQLTksjro4jF5xFRNfaOv84ae92ztWPVvdn2ImUzMndCUVg8Ux99ErZtTyg0xqJzY2DjSNTVSUil+gFGM+ouc2ZMV55gqOv6ZbpYT0XEPTZcovTMV8oXulhKjVNB1mWncXUK+bJYX8VUs3ofYCI3FHzJtfUojqmkTbMvoYA5YVpl1aiDqzZMSk2xgp6LeZtiUYZ/olhuT1Je5+PEAnr2tlw7QZjS1f5t+jbfQ9QlQrM6GKPTRyOq6iOPSJ7X2P8tonpJmZ0PSAhlKdhY95JlMd3lbyCXmImdB66rkPufuT5BNif6//jbpSb1Cx+IR8xQzGUlaqdyQli09I9lqGjEbKxX/i+4RY97xbqBb/EeYVEl7/RhtVpcz/uUleIReuZkr7hKpSz1GxeYXEL+LPKSoVfvhsfiFtTGmFkMeo2PxCdjKlbaCo1CIqNr+Qnujt7sIbX+z5hF9IMJaxvFcpKvUpFZtfiJrJWN7D1HI/X6jYPEOi19EEajm3UrJ4hkTf4gE8Asn5gJLFM2QxY1phx8XplNDP/OMZsoAx7UGKOb9HHhRX1LU/aV55htzPmDb4KNWcP5ffqGtVs9uOXP6r+oWEX0PwEmUtOLT16x2H+/TrskJODGDMGLSPuq2sEPMVt2BqloalrJDHmbps/iU6ceWEHEveWJuf/N2QU05IE0NRU36mGVVGyB7nI8fKpb/SD53++GbT8gg5FZ8s6F+3Zvc5c+1eOvn9qobB1DNvfxcaQ8XQo07n7mbEaeB1k2vrbh9X9a+eFbIx6egdTAhgpS3Ycj0DElhq2TdX9JEpW6OynfXRHwYCesxVgt7uXevm/fMNiVJVjprWsKCpuampedlT9VNHXkH5f/9pmczfe5cyyr2+jvgAAAAASUVORK5CYII=" width="100" height="100" alt="Luthier-CI" class="logo" />
<h1>Welcome to Luthier CI</h1>
<p class="version">Version <?= LUTHIER_CI_VERSION ;?></p>
<p class="links">
<a href="https://github.com/ingeniasoftware/luthier-ci">GitHub</a> &middot;
<a href="https://luthier.ingenia.me/ci/en/docs">Documentation</a>
<a href="https://luthier.ingenia.me/ci/es/docs">(Español)</a> &middot;
<a href="https://forum.codeigniter.com/thread-70497.html">Help</a>
</p>
<?php if(route_exists('login') && class_exists('Auth')){ ?>
<p>
Auth:
<?php if( Auth::isGuest() ){ ?>
<a href="<?= route('login') ;?>">Login</a>
<?php if(route_exists('signup')){ ?>
&middot;
<a href="<?= route('signup') ;?>">Sign up</a>
<?php }?>
<?php } else { ?>
<form method="post" action="<?= route('logout') ;?>">
<?php if( config_item('csrf_protection') === TRUE) { ?>
<?php
$csrf = array(
'name' => ci()->security->get_csrf_token_name(),
'hash' => ci()->security->get_csrf_hash()
);
?>
<input type="hidden" name="<?= $csrf['name'] ;?>" value="<?= $csrf['hash'] ;?>" />
<?php } ?>
<input type="submit" value="Log out" />
</form>
<?php }?>
</p>
<?php } ?>
</div>
</body>
</html>
<?php
/**
* API Routes
*
* This routes only will be available under AJAX requests. This is ideal to build APIs.
*/
<?php
/**
* CLI Routes
*
* This routes only will be available under a CLI environment
*/
// To enable Luthier-CI built-in cli commands
// uncomment the followings lines:
// Luthier\Cli::maker();
// Luthier\Cli::migrations();
<?php
/**
* Luthier default controller - DO NOT EDIT OR REMOVE THIS FILE!
*
* Because CodeIgniter checks the existence of the file/class/method of the controller
* pointed in all our routes, this allows to create dynamic routes without hacking/extending
* the CI_Router class.
*/
defined('BASEPATH') OR exit('No direct script access allowed');
class LuthierController extends CI_Controller
{
/**
* Luthier CI fake index method
*/
public function index()
{
}
}
<?php
/**
* Welcome to Luthier-CI!
*
* This is your main route file. Put all your HTTP-Based routes here using the static
* Route class methods
*
* Examples:
*
* Route::get('foo', 'bar@baz');
* -> $route['foo']['GET'] = 'bar/baz';
*
* Route::post('bar', 'baz@fobie', [ 'namespace' => 'cats' ]);
* -> $route['bar']['POST'] = 'cats/baz/foobie';
*
* Route::get('blog/{slug}', 'blog@post');
* -> $route['blog/(:any)'] = 'blog/post/$1'
*/
Route::get('/', function(){
luthier_info();
})->name('homepage');
Route::set('404_override', function(){
show_404();
});
Route::set('translate_uri_dashes',FALSE);
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
@import "bootstrap";
.form-control
{
box-shadow: none !important;
}
.btn, .form-control
{
border-radius: 2px;
}
body.login
{
background: #fdfdfd;
.panel-default
{
box-shadow: 0px 0px 30px 0px #f1f1f1;
border-radius: 4px;
.panel-body
{
padding: 35px;
h3
{
margin-bottom: 30px;
}
}
}
}
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title><?= $lang('login') ;?></title>
<link rel="stylesheet" href="<?= $assetsPath ;?>/styles.css" />
</head>
<body class="login">
<div class="container" style="padding-top:50px; padding-bottom: 50px">
<div class="row">
<div class="col-md-4 col-md-offset-4 col-sm-8 col-sm-offset-2 col-xs-10 col-xs-offset-1">
<form method="post">
<div class="panel panel-default login-box">
<div class="panel-body">
<h3 class="text-center"><?= $lang('login') ;?></h3>
<?php foreach( $messages as $type => $message){ ?>
<div class="alert alert-<?= $type ;?>"><?= $lang($message) ;?></div>
<?php } ?>
<?php if( config_item('csrf_protection') === TRUE) { ?>
<?php
$csrf = array(
'name' => $this->security->get_csrf_token_name(),
'hash' => $this->security->get_csrf_hash()
);
?>
<input type="hidden" name="<?= $csrf['name'] ;?>" value="<?= $csrf['hash'] ;?>" />
<?php } ?>
<div class="form-group">
<input type="email" name="<?= config_item('auth_form_username_field'); ?>" placeholder="<?= ucwords(config_item('auth_form_username_field')); ?>" class="form-control" required />
</div>
<div class="form-group">
<input type="password" name="<?= config_item('auth_form_password_field'); ?>" placeholder="<?= ucwords(config_item('auth_form_password_field')); ?>" class="form-control" required />
</div>
<?php if( config_item('simpleauth_enable_remember_me') == true){ ?>
<div class="form-group">
<label>
<input type="checkbox" name="<?= config_item('simpleauth_remember_me_field');?>" /> <?= $lang('remember_me') ;?>
</label>
</div>
<?php } ?>
<button type="submit" class="btn btn-primary btn-block"><?= $lang('enter') ;?></button>
<?php if( config_item('simpleauth_enable_password_reset') === TRUE || config_item('simpleauth_enable_signup') === TRUE){ ?>
<hr />
<?php } ?>
<?php if(config_item('simpleauth_enable_password_reset') === TRUE){ ?>
<div class="form-group text-center">
<a href="<?= route('password_reset') ;?>">
<?= $lang('forgotten_password_link') ;?>
</a>
</div>
<?php } ?>
<?php if(config_item('simpleauth_enable_signup') === TRUE){ ?>
<div class="form-group text-center">
<a href="<?= route('signup') ;?>">
<?= $lang('register_link') ;?>
</a>
</div>
<?php } ?>
</div>
</div>
</form>
</div>
</div>
</div>
</body>
</html>
\ No newline at end of file
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title><?= $title ;?></title>
<link rel="stylesheet" href="<?= $assetsPath ;?>/styles.css" />
</head>
<body class="signup_message">
<div class="container" style="padding:25px 0">
<div class="row">
<div class="col-md-12">
<h3><?= $title ;?></h3>
<p><?= $message ;?></p>
</div>
</div>
</div>
</body>
</html>
\ No newline at end of file
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title><?= $lang('password_prompt') ;?></title>
<link rel="stylesheet" href="<?= $assetsPath ;?>/styles.css" />
</head>
<body>
<div class="container" style="padding-top:50px; padding-bottom: 50px">
<div class="row">
<div class="col-md-4 col-md-offset-4 col-sm-8 col-sm-offset-2 col-xs-10 col-xs-offset-1">
<form method="post">
<h3 class="text-center"><?= $lang('password_prompt') ;?></h3>
<?php foreach( $messages as $type => $message){ ?>
<div class="alert alert-<?= $type ;?>"><?= $message ;?></div>
<?php } ?>
<?php if( config_item('csrf_protection') === TRUE) { ?>
<?php
$csrf = array(
'name' => $this->security->get_csrf_token_name(),
'hash' => $this->security->get_csrf_hash()
);
?>
<input type="hidden" name="<?= $csrf['name'] ;?>" value="<?= $csrf['hash'] ;?>" />
<?php } ?>
<div class="form-group <?= isset($validationErrors['current_password']) ? 'has-error has-feedback' : '' ;?>">
<input type="password" name="current_password" class="form-control" required />
<?php if(isset($validationErrors['current_password'])) { ?>
<div class="help-block"><?= $validationErrors['current_password'] ;?></div>
<?php } ;?>
</div>
<button type="submit" class="btn btn-primary btn-block"><?= $lang('password_prompt_btn');?></button>
</form>
</div>
</div>
</div>
</body>
</html>
\ No newline at end of file
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title><?= $lang('password_reset') ;?></title>
<link rel="stylesheet" href="<?= $assetsPath ;?>/styles.css" />
</head>
<body>
<div class="container" style="padding-top:50px; padding-bottom: 50px">
<div class="row">
<div class="col-md-4 col-md-offset-4 col-sm-8 col-sm-offset-2 col-xs-10 col-xs-offset-1">
<form method="post">
<h3 class="text-center"><?= $lang('password_reset') ;?></h3>
<?php foreach( $messages as $type => $message){ ?>
<div class="alert alert-<?= $type ;?>"><?= $message ;?></div>
<?php } ?>
<?php if( config_item('csrf_protection') === TRUE) { ?>
<?php
$csrf = array(
'name' => $this->security->get_csrf_token_name(),
'hash' => $this->security->get_csrf_hash()
);
?>
<input type="hidden" name="<?= $csrf['name'] ;?>" value="<?= $csrf['hash'] ;?>" />
<?php } ?>
<div class="form-group <?= isset($validationErrors['email']) ? 'has-error has-feedback' : '' ;?>">
<label><?= $lang('password_reset_email_label') ;?></label>
<input type="email" name="email" class="form-control" required />
<?php if(isset($validationErrors['email'])) { ?>
<div class="help-block"><?= $validationErrors['email'] ;?></div>
<?php } ;?>
</div>
<button type="submit" class="btn btn-primary btn-block"><?= $lang('password_reset_btn') ;?></button>
</form>
</div>
</div>
</div>
</body>
</html>
\ No newline at end of file
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title><?= $lang('password_reset') ;?></title>
<link rel="stylesheet" href="<?= $assetsPath ;?>/styles.css" />
</head>
<body>
<div class="container" style="padding-top:50px; padding-bottom: 50px">
<div class="row">
<div class="col-md-4 col-md-offset-4 col-sm-8 col-sm-offset-2 col-xs-10 col-xs-offset-1">
<form method="post">
<h3 class="text-center"><?= $lang('password_reset') ;?></h3>
<?php foreach( $messages as $type => $message){ ?>
<div class="alert alert-<?= $type ;?>"><?= $message ;?></div>
<?php } ?>
<?php if( config_item('csrf_protection') === TRUE) { ?>
<?php
$csrf = array(
'name' => $this->security->get_csrf_token_name(),
'hash' => $this->security->get_csrf_hash()
);
?>
<input type="hidden" name="<?= $csrf['name'] ;?>" value="<?= $csrf['hash'] ;?>" />
<?php } ?>
<div class="form-group <?= isset($validationErrors['new_password']) ? 'has-error has-feedback' : '' ;?>">
<label><?= $lang('password_reset_new_pwd') ;?></label>
<input type="password" name="new_password" class="form-control" required />
<?php if(isset($validationErrors['new_password'])) { ?>
<div class="help-block"><?= $validationErrors['new_password'] ;?></div>
<?php } ;?>
</div>
<div class="form-group <?= isset($validationErrors['repeat_password']) ? 'has-error has-feedback' : '' ;?>">
<label><?= $lang('password_reset_repeat_pwd') ;?></label>
<input type="password" name="repeat_password" class="form-control" required />
<?php if(isset($validationErrors['repeat_password'])) { ?>
<div class="help-block"><?= $validationErrors['repeat_password'] ;?></div>
<?php } ;?>
</div>
<button type="submit" class="btn btn-primary btn-block"><?= $lang('password_reset_form_btn') ;?></button>
</form>
</div>
</div>
</div>
</body>
</html>
\ No newline at end of file
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title><?= $lang('signup') ;?></title>
<link rel="stylesheet" href="<?= $assetsPath ;?>/styles.css" />
</head>
<body class="signup">
<div class="container" style="padding-top:25px; padding-bottom: 25px">
<div class="row">
<div class="col-md-4 col-md-offset-4 col-sm-8 col-sm-offset-2 col-xs-10 col-xs-offset-1">
<form method="post">
<h3 class="text-center"><?= $lang('signup') ;?></h3>
<?php if( config_item('csrf_protection') === TRUE) { ?>
<?php
$csrf = array(
'name' => $this->security->get_csrf_token_name(),
'hash' => $this->security->get_csrf_hash()
);
?>
<input type="hidden" name="<?= $csrf['name'] ;?>" value="<?= $csrf['hash'] ;?>" />
<?php } ?>
<?php foreach( $signupFields as $name => $attrs){ ?>
<?php
if(isset($attrs['checkbox']) || isset($attrs['radio']) || isset($attrs['select']))
{
$type = isset($attrs['checkbox']) ? 'checkbox' : (isset($attrs['radio']) ? 'radio' : 'select');
$values = $attrs[$type];
unset($attrs[$type]);
list($label, $htmlAttrs) = $attrs;
}
else
{
list($type, $label, $htmlAttrs) = $attrs;
}
?>
<div class="form-group <?= isset($validationErrors[$name]) ? 'has-error has-feedback' : '' ;?>">
<label><?= $label ;?></label>
<?php if(!in_array($type, ['checkbox', 'radio', 'select'])){ ?>
<input name="<?= $name ;?>" type="<?= $type ;?>"
<?php
if(!isset($htmlAttrs['class']))
{
echo 'class="form-control"';
}
foreach($htmlAttrs as $_name => $_value)
{
if($_name == 'value')
{
continue;
}
echo $_name . (!empty($_value) ? '="' . ( !is_bool($_value) ? $_value : ($_value === true ? 'true' : 'false') ) .'"' : '');
}
if($type != 'password')
{
echo 'value="' . set_value($name) . '"';
}
?>
/>
<?php } else { ?>
<?php if($type != 'select') { ?>
<?php foreach($values as $_value => $_label){ ?>
<label style="display:block; font-weight: normal">
<input type="<?= $type ;?>" name="<?= $name ;?>" value="<?= $_value;?> "/> <?= $_label ;?>
</label>
<?php } ?>
<?php } else { ?>
<select name="<?= $name ;?>"
<?php
if(!isset($htmlAttrs['class']))
{
echo 'class="form-control"';
}
foreach($htmlAttrs as $_name => $_value)
{
if($_name == 'value')
{
continue;
}
echo $_name . (!empty($_value) ? '="' . ( $_name == 'required' ? 'required' : ( !is_bool($_value) ? $_value : ($_value === true ? 'true' : 'false') ) ) .'"' : '');
}
?>
>
<?php foreach($values as $_value => $_label){ ?>
<option value="<?= $_value ;?>" <?= set_value($name) == $_value ? 'selected="selected"' : '' ;?>><?= $_label ; ?></option>
<?php } ?>
</select>
<?php } ?>
<?php } ?>
<?php if(isset($validationErrors[$name])) { ?>
<div class="help-block"><?= $validationErrors[$name] ;?></div>
<?php } ;?>
</div>
<?php } ?>
<button type="submit" class="btn btn-primary btn-block"><?= $lang('signup_btn') ;?></button>
</form>
</div>
</div>
</div>
</body>
</html>
\ No newline at end of file
<?php
/**
* --------------------------------------------------------------------------------------
* General Auth configuration
* --------------------------------------------------------------------------------------
*/
//
// Basic routing
//
$config['auth_login_route'] = 'login';
$config['auth_logout_route'] = 'logout';
$config['auth_login_route_redirect'] = 'dashboard';
$config['auth_logout_route_redirect'] = 'homepage';
$config['auth_route_auto_redirect'] = [
# The following routes will redirect to the 'auth_login_route_redirect' if
# the user is logged in:
'login',
'signup',
'password_reset',
'password_reset_form'
];
//
// Main login form
//
$config['auth_form_username_field'] = 'email';
$config['auth_form_password_field'] = 'password';
//
// Session & Cookies configuration
//
$config['auth_session_var'] = 'auth';
/**
* --------------------------------------------------------------------------------------
* SimpleAuth configuration
* --------------------------------------------------------------------------------------
*/
//
// Enable/disable features
//
$config['simpleauth_enable_signup'] = TRUE;
$config['simpleauth_enable_password_reset'] = TRUE;
$config['simpleauth_enable_remember_me'] = TRUE;
$config['simpleauth_enable_email_verification'] = TRUE;
$config['simpleauth_enforce_email_verification'] = FALSE;
$config['simpleauth_enable_brute_force_protection'] = TRUE;
$config['simpleauth_enable_acl'] = TRUE ;
//
// Views configuration
//
$config['simpleauth_skin'] = 'default';
$config['simpleauth_assets_dir'] = 'assets/auth';
//
// ACL Configuration
//
$config['simpleauth_acl_map'] = [
// If you are worried about performance, you can fill this array with $key => $value
// pairs of known permissions/permissions groups ids, reducing drastically the
// amount of executed database queries
//
// Example
// [ permission full name ] [ permission id ]
// 'general.blog.read' => 1
// 'general.blog.edit' => 2
// 'general.blog.delete' => 3
];
//
// Email configuration
//
$config['simpleauth_email_configuration'] = null;
$config['simpleauth_email_address'] = 'noreply@example.com';
$config['simpleauth_email_name'] = 'Example';
$config['simpleauth_email_verification_message'] = NULL;
$config['simpleauth_password_reset_message'] = NULL;
//
// Remember me configuration
//
$config['simpleauth_remember_me_field'] = 'remember_me';
$config['simpleauth_remember_me_cookie'] = 'remember_me';
//
// Database configuration
//
$config['simpleauth_user_provider'] = 'User';
$config['simpleauth_users_table'] = 'users';
$config['simpleauth_users_email_verification_table'] = 'email_verifications';
$config['simpleauth_password_resets_table'] = 'password_resets';
$config['simpleauth_login_attempts_table'] = 'login_attempts';
$config['simpleauth_users_acl_table'] = 'user_permissions';
$config['simpleauth_users_acl_categories_table'] = 'user_permissions_categories';
$config['simpleauth_id_col'] = 'id';
$config['simpleauth_username_col'] = 'email';
$config['simpleauth_email_col'] = 'email';
$config['simpleauth_email_first_name_col'] = 'first_name';
$config['simpleauth_password_col'] = 'password';
$config['simpleauth_role_col'] = 'role';
$config['simpleauth_active_col'] = 'active';
$config['simpleauth_verified_col'] = 'verified';
$config['simpleauth_remember_me_col'] = 'remember_token';
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Welcome to your SimpleAuth controller!
*
* This class inherits the Luthier-CI base SimpleAuth controller, which contains
* all the authentication logic out-the-box.
*
* (And yes, is still a controller, so you can add your own methods)
*/
class SimpleAuthController extends Luthier\Auth\SimpleAuth\Controller
{
/**
* Sign up form fields
*
* This method must return an array with the Sign up form fields and their respective
* validation.
*
* Feel free to modify this array, it's YOUR sign up form ;)
*
* The syntax is the following:
*
* [
* [field name] => [
* [field type],
* [field label],
* [HTML5 attributes] (In key => value array format),
* [CI Validation] (array of validation rules),
* [CI Validation Messages] (array, optional)
* ]
* ]
*
* @return mixed
*
* @access public
*/
public function getSignupFields()
{
return [
'first_name' => [
'text',
'First Name',
['required' => true],
['required', 'max_length[45]'],
null
],
'last_name' => [
'text',
'Last Name',
['required' => 'required'],
['required', 'max_length[45]'],
],
'username' => [
'text',
'Username',
['required' => true, 'max_length' => 22],
['required', 'min_length[3]', 'max_length[22]', 'is_unique[' . config_item('simpleauth_users_table') . '.username' . ']'],
],
'email' => [
'email',
'Email',
['required' => true],
['required', 'valid_email', 'max_length[255]', 'is_unique[' . config_item('simpleauth_users_table') . '.' . config_item('simpleauth_username_col') .']'],
],
'gender' => [
'radio' => [ 'm' => 'Male', 'f' => 'Female'],
'Gender',
['required' => true],
['required', 'max_length[45]'],
],
'password' => [
'password',
'Password',
['required' => true],
['required', 'min_length[8]', 'matches[password_repeat]'],
['matches' => 'The passwords does not match.'],
],
'password_repeat' => [
'password',
'Repeat Password',
['required' => true],
['required']
],
'tos_agreement' => [
'checkbox' => [ 'accept' => 'I accept the Terms and Conditions of Service'],
'Conditions agreement',
['required' => true],
['required'],
['required' => 'You must accept the Terms and Conditions of Service']
],
];
}
/**
* Fillable database user fields
*
* This method must return an array with the database fillable user fields.
*
* (In other words, this is the equivalent of the $fillable property of Eloquent ORM
* models, but only for auth proposes)
*
* @return array
*
* @access public
*/
public function getUserFields()
{
return [
'first_name',
'last_name',
'username',
'gender',
'email',
'password',
'role' => 'user',
'created_at' => date('Y-m-d H:i:s'),
];
}
}
\ No newline at end of file
<?php
/**
* SimpleAuth library
*
* This is a wrapper of Luthier-CI Standard Auth Library (Luthier\Auth) with some
* useful functions.
*
* @autor Anderson Salas <anderson@ingenia.me>
* @licence MIT
*/
class Simple_auth extends Luthier\Auth\SimpleAuth\Library
{
}
\ No newline at end of file
<?php
/**
* SimpleAuthMiddleware class
*
* This middleware is the most basic layer of security. It is responsible for verifying if
* the user is authenticated and redirects it to the login screen otherwise, and
* automatically manages the "Remember me" functionality for you.
*
* Probably more authentication logic is necessary, but that is at the discretion of
* the developer :)
*
* @autor Anderson Salas <anderson@ingenia.me>
* @licence MIT
*/
defined('BASEPATH') OR exit('No direct script access allowed');
use Luthier\Auth\SimpleAuth\Middleware\SimpleAuthMiddleware as BaseSimpleAuthMiddleware;
class SimpleAuthMiddleware extends BaseSimpleAuthMiddleware
{
}
\ No newline at end of file
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class Migration_create_users_table extends CI_Migration
{
public function __construct()
{
parent::__construct();
$this->load->config('auth');
$this->load->library('simple_auth');
}
public function up()
{
$this->dbforge->add_field([
'id' =>
[
'type' => 'INT',
'constraint' => 8,
'unsigned' => TRUE,
'auto_increment' => TRUE
],
'first_name' =>
[
'type' => 'VARCHAR',
'constraint' => 65,
],
'last_name' =>
[
'type' => 'VARCHAR',
'constraint' => 65,
],
'username' =>
[
'type' => 'VARCHAR',
'constraint' => 22,
'unique' => TRUE,
],
'gender' =>
[
'type' => 'VARCHAR',
'constraint' => 1,
],
'email' =>
[
'type' => 'VARCHAR',
'constraint' => 255,
'unique' => TRUE,
],
'password' =>
[
'type' => 'VARCHAR',
'constraint' => 255,
],
'role' =>
[
'type' => 'VARCHAR',
'constraint' => 45,
'default' => 'user'
],
'remember_token' =>
[
'type' => 'VARCHAR',
'constraint' => 128,
],
'active' =>
[
'type' => 'INT',
'constraint' => 1,
'unsigned' => TRUE,
'default' => 1,
],
'verified' =>
[
'type' => 'INT',
'constraint' => 1,
'unsigned' => TRUE,
'default' => 0,
],
'created_at DATETIME default CURRENT_TIMESTAMP',
'updated_at' =>
[
'type' => 'DATETIME',
'null' => TRUE,
],
]);
$this->dbforge->add_key('id', TRUE);
$this->dbforge->create_table('users');
//
// Create default users
// (Edit this with your values)
//
$this->simple_auth->createUser(
[
'first_name' => 'Admin',
'last_name' => 'Admin',
'username' => 'admin',
'email' => 'admin@admin.com',
'password' => 'admin',
'gender' => 'm',
'role' => 'admin',
'verified' => 1
]
);
}
public function down()
{
$this->dbforge->drop_table('users',TRUE);
}
}
\ No newline at end of file
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class Migration_create_password_resets_table extends CI_Migration
{
public function up()
{
$this->dbforge->add_field([
'id' =>
[
'type' => 'INT',
'constraint' => 8,
'unsigned' => TRUE,
'auto_increment' => TRUE
],
'email' =>
[
'type' => 'VARCHAR',
'constraint' => '255',
],
'token' =>
[
'type' => 'VARCHAR',
'constraint' => '255',
],
'active' =>
[
'type' => 'INT',
'constraint' => 1,
'default' => 1,
],
'created_at DATETIME default CURRENT_TIMESTAMP',
]);
$this->dbforge->add_key('id', TRUE);
$this->dbforge->create_table('password_resets');
}
public function down()
{
$this->dbforge->drop_table('password_resets',TRUE);
}
}
\ No newline at end of file
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class Migration_create_email_verifications_table extends CI_Migration
{
public function up()
{
$this->dbforge->add_field([
'id' =>
[
'type' => 'INT',
'constraint' => 8,
'unsigned' => TRUE,
'auto_increment' => TRUE
],
'email' =>
[
'type' => 'VARCHAR',
'constraint' => 255,
],
'token' =>
[
'type' => 'VARCHAR',
'constraint' => 255,
],
'created_at DATETIME default CURRENT_TIMESTAMP',
]);
$this->dbforge->add_key('id', TRUE);
$this->dbforge->create_table('email_verifications');
}
public function down()
{
$this->dbforge->drop_table('email_verifications',TRUE);
}
}
\ No newline at end of file
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class Migration_create_login_attempts_table extends CI_Migration
{
public function up()
{
$this->dbforge->add_field([
'id' =>
[
'type' => 'INT',
'constraint' => 8,
'unsigned' => TRUE,
'auto_increment' => TRUE
],
'username' =>
[
'type' => 'VARCHAR',
'constraint' => 255,
],
'ip' =>
[
'type' => 'VARCHAR',
'constraint' => 255,
],
'created_at DATETIME default CURRENT_TIMESTAMP',
]);
$this->dbforge->add_key('id', TRUE);
$this->dbforge->create_table('login_attempts');
}
public function down()
{
$this->dbforge->drop_table('login_attempts',TRUE);
}
}
\ No newline at end of file
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class Migration_create_user_permissions_categories_table extends CI_Migration
{
public function up()
{
$this->dbforge->add_field([
'id' =>
[
'type' => 'INT',
'constraint' => 8,
'unsigned' => TRUE,
'auto_increment' => TRUE
],
'name' =>
[
'type' => 'VARCHAR',
'constraint' => 65,
],
'parent_id' =>
[
'type' => 'INT',
'constraint' => 8,
'unsigned' => TRUE,
'null' => TRUE,
],
'created_at DATETIME default CURRENT_TIMESTAMP',
]);
$this->dbforge->add_key('id', TRUE);
$this->dbforge->add_field('CONSTRAINT FOREIGN KEY (parent_id) REFERENCES user_permissions_categories(id)');
$this->dbforge->create_table('user_permissions_categories');
}
public function down()
{
$this->dbforge->drop_table('user_permissions_categories',TRUE);
}
}
\ No newline at end of file
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
class Migration_create_user_permissions_table extends CI_Migration
{
public function up()
{
$this->dbforge->add_field([
'id' =>
[
'type' => 'INT',
'constraint' => 8,
'unsigned' => TRUE,
'auto_increment' => TRUE
],
'user_id' =>
[
'type' => 'INT',
'constraint' => 8,
'unsigned' => TRUE,
],
'category_id' =>
[
'type' => 'INT',
'constraint' => 8,
'unsigned' => TRUE,
],
'created_at DATETIME default CURRENT_TIMESTAMP',
]);
$this->dbforge->add_key('id', TRUE);
$this->dbforge->add_field('CONSTRAINT FOREIGN KEY (user_id) REFERENCES users(id)');
$this->dbforge->add_field('CONSTRAINT FOREIGN KEY (category_id) REFERENCES user_permissions_categories(id)');
$this->dbforge->create_table('user_permissions');
}
public function down()
{
$this->dbforge->drop_table('user_permissions',TRUE);
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment