├── app ├── Filters │ ├── .gitkeep │ └── AuthGuard.php ├── Helpers │ └── .gitkeep ├── Language │ ├── .gitkeep │ └── en │ │ └── Validation.php ├── Libraries │ └── .gitkeep ├── Models │ ├── .gitkeep │ └── UserModel.php ├── ThirdParty │ └── .gitkeep ├── Database │ ├── Seeds │ │ └── .gitkeep │ └── Migrations │ │ └── .gitkeep ├── .htaccess ├── Views │ ├── errors │ │ ├── cli │ │ │ ├── error_404.php │ │ │ ├── production.php │ │ │ └── error_exception.php │ │ └── html │ │ │ ├── production.php │ │ │ ├── error_404.php │ │ │ ├── debug.js │ │ │ ├── debug.css │ │ │ └── error_exception.php │ ├── signin.php │ └── signup.php ├── index.html ├── Config │ ├── ForeignCharacters.php │ ├── CURLRequest.php │ ├── Images.php │ ├── Boot │ │ ├── production.php │ │ ├── testing.php │ │ └── development.php │ ├── Honeypot.php │ ├── Publisher.php │ ├── Services.php │ ├── Feature.php │ ├── Validation.php │ ├── Pager.php │ ├── Events.php │ ├── Kint.php │ ├── Modules.php │ ├── Migrations.php │ ├── View.php │ ├── Filters.php │ ├── Generators.php │ ├── Exceptions.php │ ├── Encryption.php │ ├── Routes.php │ ├── Database.php │ ├── DocTypes.php │ ├── Format.php │ ├── Autoload.php │ ├── Paths.php │ ├── Email.php │ ├── Toolbar.php │ ├── Security.php │ ├── Cookie.php │ ├── Constants.php │ ├── ContentSecurityPolicy.php │ ├── Logger.php │ ├── Cache.php │ ├── UserAgents.php │ ├── App.php │ └── Mimes.php ├── Controllers │ ├── Home.php │ ├── ProfileController.php │ ├── SignupController.php │ ├── SigninController.php │ └── BaseController.php └── Common.php ├── public ├── robots.txt ├── favicon.ico ├── .htaccess └── index.php ├── writable ├── .htaccess ├── cache │ └── index.html ├── logs │ └── index.html ├── session │ └── index.html └── uploads │ └── index.html ├── tests ├── _support │ ├── Libraries │ │ └── ConfigReader.php │ ├── Models │ │ └── ExampleModel.php │ └── Database │ │ ├── Migrations │ │ └── 2020-02-22-222222_example_migration.php │ │ └── Seeds │ │ └── ExampleSeeder.php ├── session │ └── ExampleSessionTest.php ├── database │ └── ExampleDatabaseTest.php ├── unit │ └── HealthTest.php └── README.md ├── README.md ├── composer.json ├── LICENSE ├── .gitignore ├── phpunit.xml.dist ├── preload.php ├── spark └── env /app/Filters/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/Helpers/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/Language/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/Libraries/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/Models/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/ThirdParty/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/Database/Seeds/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/Database/Migrations/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: 3 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SinghDigamber/codeigniter-authentication-example/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /app/.htaccess: -------------------------------------------------------------------------------- 1 | 2 | Require all denied 3 | 4 | 5 | Deny from all 6 | 7 | -------------------------------------------------------------------------------- /app/Language/en/Validation.php: -------------------------------------------------------------------------------- 1 | 2 | Require all denied 3 | 4 | 5 | Deny from all 6 | 7 | -------------------------------------------------------------------------------- /app/Views/errors/cli/production.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 403 Forbidden 5 | 6 | 7 | 8 |

Directory access is forbidden.

9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /writable/cache/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 403 Forbidden 5 | 6 | 7 | 8 |

Directory access is forbidden.

9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /writable/logs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 403 Forbidden 5 | 6 | 7 | 8 |

Directory access is forbidden.

9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /writable/session/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 403 Forbidden 5 | 6 | 7 | 8 |

Directory access is forbidden.

9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /writable/uploads/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 403 Forbidden 5 | 6 | 7 | 8 |

Directory access is forbidden.

9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/Config/ForeignCharacters.php: -------------------------------------------------------------------------------- 1 | get('name'); 13 | } 14 | } -------------------------------------------------------------------------------- /app/Models/UserModel.php: -------------------------------------------------------------------------------- 1 | set('logged_in', 123); 16 | $this->assertSame(123, $session->get('logged_in')); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/Common.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Whoops! 8 | 9 | 12 | 13 | 14 | 15 |
16 | 17 |

Whoops!

18 | 19 |

We seem to have hit a snag. Please try again later...

20 | 21 |
22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /app/Filters/AuthGuard.php: -------------------------------------------------------------------------------- 1 | get('isLoggedIn')) 15 | { 16 | return redirect() 17 | ->to('/signin'); 18 | } 19 | } 20 | 21 | public function after(RequestInterface $request, ResponseInterface $response, $arguments = null) 22 | { 23 | 24 | } 25 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Codeigniter 4 Authentication Login and Registration Example 2 | 3 | Checkout the step-by-step tutorial on: 4 | 5 | Codeigniter 4 Authentication Login and Registration Tutorial [https://www.positronx.io/codeigniter-authentication-login-and-registration-tutorial/]. 6 | 7 | 8 | 9 | ## Installation & updates 10 | 11 | `composer create-project codeigniter4/appstarter` then `composer update` whenever 12 | there is a new release of the framework. 13 | 14 | When updating, check the release notes to see if there are any changes you might need to apply 15 | to your `app` folder. The affected files can be copied or merged from 16 | `vendor/codeigniter4/framework/app`. 17 | -------------------------------------------------------------------------------- /app/Config/CURLRequest.php: -------------------------------------------------------------------------------- 1 | 30 | */ 31 | public $handlers = [ 32 | 'gd' => GDHandler::class, 33 | 'imagick' => ImageMagickHandler::class, 34 | ]; 35 | } 36 | -------------------------------------------------------------------------------- /app/Config/Boot/production.php: -------------------------------------------------------------------------------- 1 | {label}'; 36 | 37 | /** 38 | * Honeypot container 39 | * 40 | * @var string 41 | */ 42 | public $container = '
{template}
'; 43 | } 44 | -------------------------------------------------------------------------------- /app/Config/Publisher.php: -------------------------------------------------------------------------------- 1 | 23 | */ 24 | public $restrictions = [ 25 | ROOTPATH => '*', 26 | FCPATH => '#\.(s?css|js|map|html?|xml|json|webmanifest|ttf|eot|woff2?|gif|jpe?g|tiff?|png|webp|bmp|ico|svg)$#i', 27 | ]; 28 | } 29 | -------------------------------------------------------------------------------- /app/Config/Services.php: -------------------------------------------------------------------------------- 1 | 35 | */ 36 | public $templates = [ 37 | 'list' => 'CodeIgniter\Validation\Views\list', 38 | 'single' => 'CodeIgniter\Validation\Views\single', 39 | ]; 40 | 41 | //-------------------------------------------------------------------- 42 | // Rules 43 | //-------------------------------------------------------------------- 44 | } 45 | -------------------------------------------------------------------------------- /app/Config/Pager.php: -------------------------------------------------------------------------------- 1 | 22 | */ 23 | public $templates = [ 24 | 'default_full' => 'CodeIgniter\Pager\Views\default_full', 25 | 'default_simple' => 'CodeIgniter\Pager\Views\default_simple', 26 | 'default_head' => 'CodeIgniter\Pager\Views\default_head', 27 | ]; 28 | 29 | /** 30 | * -------------------------------------------------------------------------- 31 | * Items Per Page 32 | * -------------------------------------------------------------------------- 33 | * 34 | * The default number of results shown in a single page. 35 | * 36 | * @var int 37 | */ 38 | public $perPage = 20; 39 | } 40 | -------------------------------------------------------------------------------- /tests/_support/Database/Migrations/2020-02-22-222222_example_migration.php: -------------------------------------------------------------------------------- 1 | forge->addField('id'); 14 | $this->forge->addField([ 15 | 'name' => ['type' => 'varchar', 'constraint' => 31], 16 | 'uid' => ['type' => 'varchar', 'constraint' => 31], 17 | 'class' => ['type' => 'varchar', 'constraint' => 63], 18 | 'icon' => ['type' => 'varchar', 'constraint' => 31], 19 | 'summary' => ['type' => 'varchar', 'constraint' => 255], 20 | 'created_at' => ['type' => 'datetime', 'null' => true], 21 | 'updated_at' => ['type' => 'datetime', 'null' => true], 22 | 'deleted_at' => ['type' => 'datetime', 'null' => true], 23 | ]); 24 | 25 | $this->forge->addKey('name'); 26 | $this->forge->addKey('uid'); 27 | $this->forge->addKey(['deleted_at', 'id']); 28 | $this->forge->addKey('created_at'); 29 | 30 | $this->forge->createTable('factories'); 31 | } 32 | 33 | public function down() 34 | { 35 | $this->forge->dropTable('factories'); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/Config/Boot/testing.php: -------------------------------------------------------------------------------- 1 | findAll(); 23 | 24 | // Make sure the count is as expected 25 | $this->assertCount(3, $objects); 26 | } 27 | 28 | public function testSoftDeleteLeavesRow() 29 | { 30 | $model = new ExampleModel(); 31 | $this->setPrivateProperty($model, 'useSoftDeletes', true); 32 | $this->setPrivateProperty($model, 'tempUseSoftDeletes', true); 33 | 34 | $object = $model->first(); 35 | $model->delete($object->id); 36 | 37 | // The model should no longer find it 38 | $this->assertNull($model->find($object->id)); 39 | 40 | // ... but it should still be in the database 41 | $result = $model->builder()->where('id', $object->id)->get()->getResult(); 42 | 43 | $this->assertCount(1, $result); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /tests/_support/Database/Seeds/ExampleSeeder.php: -------------------------------------------------------------------------------- 1 | 'Test Factory', 14 | 'uid' => 'test001', 15 | 'class' => 'Factories\Tests\NewFactory', 16 | 'icon' => 'fas fa-puzzle-piece', 17 | 'summary' => 'Longer sample text for testing', 18 | ], 19 | [ 20 | 'name' => 'Widget Factory', 21 | 'uid' => 'widget', 22 | 'class' => 'Factories\Tests\WidgetPlant', 23 | 'icon' => 'fas fa-puzzle-piece', 24 | 'summary' => 'Create widgets in your factory', 25 | ], 26 | [ 27 | 'name' => 'Evil Factory', 28 | 'uid' => 'evil-maker', 29 | 'class' => 'Factories\Evil\MyFactory', 30 | 'icon' => 'fas fa-book-dead', 31 | 'summary' => 'Abandon all hope, ye who enter here', 32 | ], 33 | ]; 34 | 35 | $builder = $this->db->table('factories'); 36 | 37 | foreach ($factories as $factory) { 38 | $builder->insert($factory); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/Config/Boot/development.php: -------------------------------------------------------------------------------- 1 | 'required|min_length[2]|max_length[50]', 21 | 'email' => 'required|min_length[4]|max_length[100]|valid_email|is_unique[users.email]', 22 | 'password' => 'required|min_length[4]|max_length[50]', 23 | 'confirmpassword' => 'matches[password]' 24 | ]; 25 | 26 | if($this->validate($rules)){ 27 | $userModel = new UserModel(); 28 | 29 | $data = [ 30 | 'name' => $this->request->getVar('name'), 31 | 'email' => $this->request->getVar('email'), 32 | 'password' => password_hash($this->request->getVar('password'), PASSWORD_DEFAULT) 33 | ]; 34 | 35 | $userModel->save($data); 36 | 37 | return redirect()->to('/signin'); 38 | }else{ 39 | $data['validation'] = $this->validator; 40 | echo view('signup', $data); 41 | } 42 | 43 | } 44 | 45 | } -------------------------------------------------------------------------------- /app/Controllers/SigninController.php: -------------------------------------------------------------------------------- 1 | request->getVar('email'); 23 | $password = $this->request->getVar('password'); 24 | 25 | $data = $userModel->where('email', $email)->first(); 26 | 27 | if($data){ 28 | $pass = $data['password']; 29 | $authenticatePassword = password_verify($password, $pass); 30 | if($authenticatePassword){ 31 | $ses_data = [ 32 | 'id' => $data['id'], 33 | 'name' => $data['name'], 34 | 'email' => $data['email'], 35 | 'isLoggedIn' => TRUE 36 | ]; 37 | 38 | $session->set($ses_data); 39 | return redirect()->to('/profile'); 40 | 41 | }else{ 42 | $session->setFlashdata('msg', 'Password is incorrect.'); 43 | return redirect()->to('/signin'); 44 | } 45 | 46 | }else{ 47 | $session->setFlashdata('msg', 'Email does not exist.'); 48 | return redirect()->to('/signin'); 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /app/Controllers/BaseController.php: -------------------------------------------------------------------------------- 1 | session = \Config\Services::session(); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /tests/unit/HealthTest.php: -------------------------------------------------------------------------------- 1 | assertTrue(defined('APPPATH')); 16 | } 17 | 18 | public function testBaseUrlHasBeenSet() 19 | { 20 | $validation = Services::validation(); 21 | 22 | $env = false; 23 | 24 | // Check the baseURL in .env 25 | if (is_file(HOMEPATH . '.env')) { 26 | $env = preg_grep('/^app\.baseURL = ./', file(HOMEPATH . '.env')) !== false; 27 | } 28 | 29 | if ($env) { 30 | // BaseURL in .env is a valid URL? 31 | // phpunit.xml.dist sets app.baseURL in $_SERVER 32 | // So if you set app.baseURL in .env, it takes precedence 33 | $config = new App(); 34 | $this->assertTrue( 35 | $validation->check($config->baseURL, 'valid_url'), 36 | 'baseURL "' . $config->baseURL . '" in .env is not valid URL' 37 | ); 38 | } 39 | 40 | // Get the baseURL in app/Config/App.php 41 | // You can't use Config\App, because phpunit.xml.dist sets app.baseURL 42 | $reader = new ConfigReader(); 43 | 44 | // BaseURL in app/Config/App.php is a valid URL? 45 | $this->assertTrue( 46 | $validation->check($reader->baseURL, 'valid_url'), 47 | 'baseURL "' . $reader->baseURL . '" in app/Config/App.php is not valid URL' 48 | ); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/Views/signin.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Codeigniter Login with Email/Password Example 9 | 10 | 11 |
12 |
13 |
14 | 15 |

Login in

16 | 17 | getFlashdata('msg')):?> 18 |
19 | getFlashdata('msg') ?> 20 |
21 | 22 | 23 |
24 |
25 | 26 |
27 | 28 |
29 | 30 |
31 | 32 |
33 | 34 |
35 |
36 |
37 | 38 |
39 |
40 | 41 | -------------------------------------------------------------------------------- /app/Config/Events.php: -------------------------------------------------------------------------------- 1 | 0) { 32 | ob_end_flush(); 33 | } 34 | 35 | ob_start(static fn ($buffer) => $buffer); 36 | } 37 | 38 | /* 39 | * -------------------------------------------------------------------- 40 | * Debug Toolbar Listeners. 41 | * -------------------------------------------------------------------- 42 | * If you delete, they will no longer be collected. 43 | */ 44 | if (CI_DEBUG && ! is_cli()) { 45 | Events::on('DBQuery', 'CodeIgniter\Debug\Toolbar\Collectors\Database::collect'); 46 | Services::toolbar()->respond(); 47 | } 48 | }); 49 | -------------------------------------------------------------------------------- /app/Config/Kint.php: -------------------------------------------------------------------------------- 1 | 11 | Options +FollowSymlinks 12 | RewriteEngine On 13 | 14 | # If you installed CodeIgniter in a subfolder, you will need to 15 | # change the following line to match the subfolder you need. 16 | # http://httpd.apache.org/docs/current/mod/mod_rewrite.html#rewritebase 17 | # RewriteBase / 18 | 19 | # Redirect Trailing Slashes... 20 | RewriteCond %{REQUEST_FILENAME} !-d 21 | RewriteCond %{REQUEST_URI} (.+)/$ 22 | RewriteRule ^ %1 [L,R=301] 23 | 24 | # Rewrite "www.example.com -> example.com" 25 | RewriteCond %{HTTPS} !=on 26 | RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC] 27 | RewriteRule ^ http://%1%{REQUEST_URI} [R=301,L] 28 | 29 | # Checks to see if the user is attempting to access a valid file, 30 | # such as an image or css document, if this isn't true it sends the 31 | # request to the front controller, index.php 32 | RewriteCond %{REQUEST_FILENAME} !-f 33 | RewriteCond %{REQUEST_FILENAME} !-d 34 | RewriteRule ^([\s\S]*)$ index.php/$1 [L,NC,QSA] 35 | 36 | # Ensure Authorization header is passed along 37 | RewriteCond %{HTTP:Authorization} . 38 | RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] 39 | 40 | 41 | 42 | # If we don't have mod_rewrite installed, all 404's 43 | # can be sent to index.php, and everything works as normal. 44 | ErrorDocument 404 index.php 45 | 46 | 47 | # Disable server signature start 48 | ServerSignature Off 49 | # Disable server signature end 50 | -------------------------------------------------------------------------------- /app/Config/Migrations.php: -------------------------------------------------------------------------------- 1 | php spark migrate:create 46 | * 47 | * Typical formats: 48 | * - YmdHis_ 49 | * - Y-m-d-His_ 50 | * - Y_m_d_His_ 51 | * 52 | * @var string 53 | */ 54 | public $timestampFormat = 'Y-m-d-His_'; 55 | } 56 | -------------------------------------------------------------------------------- /app/Config/View.php: -------------------------------------------------------------------------------- 1 | [] 54 | */ 55 | public array $decorators = []; 56 | } 57 | -------------------------------------------------------------------------------- /app/Views/signup.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Codeigniter Auth User Registration Example 10 | 11 | 12 | 13 | 14 | 15 |
16 |
17 |
18 |

Register User

19 | 20 | 21 |
22 | listErrors() ?> 23 |
24 | 25 | 26 |
27 |
28 | 29 |
30 | 31 |
32 | 33 |
34 | 35 |
36 | 37 |
38 | 39 |
40 | 41 |
42 | 43 |
44 | 45 |
46 |
47 |
48 |
49 |
50 | 51 | 52 | -------------------------------------------------------------------------------- /app/Config/Filters.php: -------------------------------------------------------------------------------- 1 | \CodeIgniter\Filters\CSRF::class, 22 | 'toolbar' => \CodeIgniter\Filters\DebugToolbar::class, 23 | 'honeypot' => \CodeIgniter\Filters\Honeypot::class, 24 | 'authGuard' => \App\Filters\AuthGuard::class, 25 | ]; 26 | 27 | /** 28 | * List of filter aliases that are always 29 | * applied before and after every request. 30 | * 31 | * @var array 32 | */ 33 | public $globals = [ 34 | 'before' => [ 35 | // 'honeypot', 36 | // 'csrf', 37 | // 'invalidchars', 38 | ], 39 | 'after' => [ 40 | 'toolbar', 41 | // 'honeypot', 42 | // 'secureheaders', 43 | ], 44 | ]; 45 | 46 | /** 47 | * List of filter aliases that works on a 48 | * particular HTTP method (GET, POST, etc.). 49 | * 50 | * Example: 51 | * 'post' => ['foo', 'bar'] 52 | * 53 | * If you use this, you should disable auto-routing because auto-routing 54 | * permits any HTTP method to access a controller. Accessing the controller 55 | * with a method you don’t expect could bypass the filter. 56 | * 57 | * @var array 58 | */ 59 | public $methods = []; 60 | 61 | /** 62 | * List of filter aliases that should run on any 63 | * before or after URI patterns. 64 | * 65 | * Example: 66 | * 'isLoggedIn' => ['before' => ['account/*', 'profiles/*']] 67 | * 68 | * @var array 69 | */ 70 | public $filters = []; 71 | } 72 | -------------------------------------------------------------------------------- /app/Config/Generators.php: -------------------------------------------------------------------------------- 1 | 27 | */ 28 | public $views = [ 29 | 'make:command' => 'CodeIgniter\Commands\Generators\Views\command.tpl.php', 30 | 'make:config' => 'CodeIgniter\Commands\Generators\Views\config.tpl.php', 31 | 'make:controller' => 'CodeIgniter\Commands\Generators\Views\controller.tpl.php', 32 | 'make:entity' => 'CodeIgniter\Commands\Generators\Views\entity.tpl.php', 33 | 'make:filter' => 'CodeIgniter\Commands\Generators\Views\filter.tpl.php', 34 | 'make:migration' => 'CodeIgniter\Commands\Generators\Views\migration.tpl.php', 35 | 'make:model' => 'CodeIgniter\Commands\Generators\Views\model.tpl.php', 36 | 'make:seeder' => 'CodeIgniter\Commands\Generators\Views\seeder.tpl.php', 37 | 'make:validation' => 'CodeIgniter\Commands\Generators\Views\validation.tpl.php', 38 | 'session:migration' => 'CodeIgniter\Commands\Generators\Views\migration.tpl.php', 39 | ]; 40 | } 41 | -------------------------------------------------------------------------------- /app/Config/Exceptions.php: -------------------------------------------------------------------------------- 1 | getFile()) . ':' . $exception->getLine(), 'green')); 12 | CLI::newLine(); 13 | 14 | // The backtrace 15 | if (defined('SHOW_DEBUG_BACKTRACE') && SHOW_DEBUG_BACKTRACE) { 16 | $backtraces = $exception->getTrace(); 17 | 18 | if ($backtraces) { 19 | CLI::write('Backtrace:', 'green'); 20 | } 21 | 22 | foreach ($backtraces as $i => $error) { 23 | $padFile = ' '; // 4 spaces 24 | $padClass = ' '; // 7 spaces 25 | $c = str_pad($i + 1, 3, ' ', STR_PAD_LEFT); 26 | 27 | if (isset($error['file'])) { 28 | $filepath = clean_path($error['file']) . ':' . $error['line']; 29 | 30 | CLI::write($c . $padFile . CLI::color($filepath, 'yellow')); 31 | } else { 32 | CLI::write($c . $padFile . CLI::color('[internal function]', 'yellow')); 33 | } 34 | 35 | $function = ''; 36 | 37 | if (isset($error['class'])) { 38 | $type = ($error['type'] === '->') ? '()' . $error['type'] : $error['type']; 39 | $function .= $padClass . $error['class'] . $type . $error['function']; 40 | } elseif (! isset($error['class']) && isset($error['function'])) { 41 | $function .= $padClass . $error['function']; 42 | } 43 | 44 | $args = implode(', ', array_map(static function ($value) { 45 | switch (true) { 46 | case is_object($value): 47 | return 'Object(' . get_class($value) . ')'; 48 | 49 | case is_array($value): 50 | return count($value) ? '[...]' : '[]'; 51 | 52 | case $value === null: 53 | return 'null'; // return the lowercased version 54 | 55 | default: 56 | return var_export($value, true); 57 | } 58 | }, array_values($error['args'] ?? []))); 59 | 60 | $function .= '(' . $args . ')'; 61 | 62 | CLI::write($function); 63 | CLI::newLine(); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /app/Views/errors/html/error_404.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 404 Page Not Found 6 | 7 | 70 | 71 | 72 |
73 |

404 - File Not Found

74 | 75 |

76 | 77 | 78 | 79 | Sorry! Cannot seem to find the page you were looking for. 80 | 81 |

82 |
83 | 84 | 85 | -------------------------------------------------------------------------------- /public/index.php: -------------------------------------------------------------------------------- 1 | systemDirectory, '\\/ ') . DIRECTORY_SEPARATOR . 'bootstrap.php'; 39 | 40 | // Load environment settings from .env files into $_SERVER and $_ENV 41 | require_once SYSTEMPATH . 'Config/DotEnv.php'; 42 | (new CodeIgniter\Config\DotEnv(ROOTPATH))->load(); 43 | 44 | /* 45 | * --------------------------------------------------------------- 46 | * GRAB OUR CODEIGNITER INSTANCE 47 | * --------------------------------------------------------------- 48 | * 49 | * The CodeIgniter class contains the core functionality to make 50 | * the application run, and does all of the dirty work to get 51 | * the pieces all working together. 52 | */ 53 | 54 | $app = Config\Services::codeigniter(); 55 | $app->initialize(); 56 | $context = is_cli() ? 'php-cli' : 'web'; 57 | $app->setContext($context); 58 | 59 | /* 60 | *--------------------------------------------------------------- 61 | * LAUNCH THE APPLICATION 62 | *--------------------------------------------------------------- 63 | * Now that everything is setup, it's time to actually fire 64 | * up the engines and make this app do its thang. 65 | */ 66 | 67 | $app->run(); 68 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | #------------------------- 2 | # Operating Specific Junk Files 3 | #------------------------- 4 | 5 | # OS X 6 | .DS_Store 7 | .AppleDouble 8 | .LSOverride 9 | 10 | # OS X Thumbnails 11 | ._* 12 | 13 | # Windows image file caches 14 | Thumbs.db 15 | ehthumbs.db 16 | Desktop.ini 17 | 18 | # Recycle Bin used on file shares 19 | $RECYCLE.BIN/ 20 | 21 | # Windows Installer files 22 | *.cab 23 | *.msi 24 | *.msm 25 | *.msp 26 | 27 | # Windows shortcuts 28 | *.lnk 29 | 30 | # Linux 31 | *~ 32 | 33 | # KDE directory preferences 34 | .directory 35 | 36 | # Linux trash folder which might appear on any partition or disk 37 | .Trash-* 38 | 39 | #------------------------- 40 | # Environment Files 41 | #------------------------- 42 | # These should never be under version control, 43 | # as it poses a security risk. 44 | .env 45 | .vagrant 46 | Vagrantfile 47 | 48 | #------------------------- 49 | # Temporary Files 50 | #------------------------- 51 | writable/cache/* 52 | !writable/cache/index.html 53 | 54 | writable/logs/* 55 | !writable/logs/index.html 56 | 57 | writable/session/* 58 | !writable/session/index.html 59 | 60 | writable/uploads/* 61 | !writable/uploads/index.html 62 | 63 | writable/debugbar/* 64 | 65 | php_errors.log 66 | 67 | #------------------------- 68 | # User Guide Temp Files 69 | #------------------------- 70 | user_guide_src/build/* 71 | user_guide_src/cilexer/build/* 72 | user_guide_src/cilexer/dist/* 73 | user_guide_src/cilexer/pycilexer.egg-info/* 74 | 75 | #------------------------- 76 | # Test Files 77 | #------------------------- 78 | tests/coverage* 79 | 80 | # Don't save phpunit under version control. 81 | phpunit 82 | 83 | #------------------------- 84 | # Composer 85 | #------------------------- 86 | vendor/ 87 | 88 | #------------------------- 89 | # IDE / Development Files 90 | #------------------------- 91 | 92 | # Modules Testing 93 | _modules/* 94 | 95 | # phpenv local config 96 | .php-version 97 | 98 | # Jetbrains editors (PHPStorm, etc) 99 | .idea/ 100 | *.iml 101 | 102 | # Netbeans 103 | nbproject/ 104 | build/ 105 | nbbuild/ 106 | dist/ 107 | nbdist/ 108 | nbactions.xml 109 | nb-configuration.xml 110 | .nb-gradle/ 111 | 112 | # Sublime Text 113 | *.tmlanguage.cache 114 | *.tmPreferences.cache 115 | *.stTheme.cache 116 | *.sublime-workspace 117 | *.sublime-project 118 | .phpintel 119 | /api/ 120 | 121 | # Visual Studio Code 122 | .vscode/ 123 | 124 | /results/ 125 | /phpunit*.xml 126 | /.phpunit.*.cache 127 | 128 | -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | 16 | ./app 17 | 18 | 19 | ./app/Views 20 | ./app/Config/Routes.php 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | ./tests 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /app/Config/Routes.php: -------------------------------------------------------------------------------- 1 | setDefaultNamespace('App\Controllers'); 20 | $routes->setDefaultController('Home'); 21 | $routes->setDefaultMethod('index'); 22 | $routes->setTranslateURIDashes(false); 23 | $routes->set404Override(); 24 | 25 | 26 | // The Auto Routing (Legacy) is very dangerous. It is easy to create vulnerable apps 27 | // where controller filters or CSRF protection are bypassed. 28 | // If you don't want to define all routes, please use the Auto Routing (Improved). 29 | // Set `$autoRoutesImproved` to true in `app/Config/Feature.php` and set the following to true. 30 | //$routes->setAutoRoute(false); 31 | 32 | /* 33 | * -------------------------------------------------------------------- 34 | * Route Definitions 35 | * -------------------------------------------------------------------- 36 | */ 37 | 38 | // We get a performance increase by specifying the default 39 | // route since we don't have to scan directories. 40 | // $routes->get('/', 'Home::index'); 41 | 42 | $routes->get('/', 'SignupController::index'); 43 | $routes->get('/signup', 'SignupController::index'); 44 | $routes->match(['get', 'post'], 'SignupController/store', 'SignupController::store'); 45 | $routes->match(['get', 'post'], 'SigninController/loginAuth', 'SigninController::loginAuth'); 46 | $routes->get('/signin', 'SigninController::index'); 47 | $routes->get('/profile', 'ProfileController::index',['filter' => 'authGuard']); 48 | 49 | /* 50 | * -------------------------------------------------------------------- 51 | * Additional Routing 52 | * -------------------------------------------------------------------- 53 | * 54 | * There will often be times that you need additional routing and you 55 | * need it to be able to override any defaults in this file. Environment 56 | * based routes is one such time. require() additional route files here 57 | * to make that happen. 58 | * 59 | * You will have access to the $routes object within that file without 60 | * needing to reload it. 61 | */ 62 | if (is_file(APPPATH . 'Config/' . ENVIRONMENT . '/Routes.php')) { 63 | require APPPATH . 'Config/' . ENVIRONMENT . '/Routes.php'; 64 | } 65 | -------------------------------------------------------------------------------- /app/Config/Database.php: -------------------------------------------------------------------------------- 1 | '', 35 | 'hostname' => 'localhost', 36 | 'username' => 'root', 37 | 'password' => 'root', 38 | 'database' => 'demo', 39 | 'DBDriver' => 'MySQLi', 40 | 'DBPrefix' => '', 41 | 'pConnect' => false, 42 | 'DBDebug' => (ENVIRONMENT !== 'production'), 43 | 'charset' => 'utf8', 44 | 'DBCollat' => 'utf8_general_ci', 45 | 'swapPre' => '', 46 | 'encrypt' => false, 47 | 'compress' => false, 48 | 'strictOn' => false, 49 | 'failover' => [], 50 | 'port' => 3306, 51 | ]; 52 | 53 | /** 54 | * This database connection is used when 55 | * running PHPUnit database tests. 56 | * 57 | * @var array 58 | */ 59 | public $tests = [ 60 | 'DSN' => '', 61 | 'hostname' => '127.0.0.1', 62 | 'username' => '', 63 | 'password' => '', 64 | 'database' => ':memory:', 65 | 'DBDriver' => 'SQLite3', 66 | 'DBPrefix' => 'db_', // Needed to ensure we're working correctly with prefixes live. DO NOT REMOVE FOR CI DEVS 67 | 'pConnect' => false, 68 | 'DBDebug' => (ENVIRONMENT !== 'production'), 69 | 'charset' => 'utf8', 70 | 'DBCollat' => 'utf8_general_ci', 71 | 'swapPre' => '', 72 | 'encrypt' => false, 73 | 'compress' => false, 74 | 'strictOn' => false, 75 | 'failover' => [], 76 | 'port' => 3306, 77 | 'foreignKeys' => true, 78 | ]; 79 | 80 | public function __construct() 81 | { 82 | parent::__construct(); 83 | 84 | // Ensure that we always set the database group to 'tests' if 85 | // we are currently running an automated test suite, so that 86 | // we don't overwrite live data on accident. 87 | if (ENVIRONMENT === 'testing') { 88 | $this->defaultGroup = 'tests'; 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /app/Config/DocTypes.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | public $list = [ 13 | 'xhtml11' => '', 14 | 'xhtml1-strict' => '', 15 | 'xhtml1-trans' => '', 16 | 'xhtml1-frame' => '', 17 | 'xhtml-basic11' => '', 18 | 'html5' => '', 19 | 'html4-strict' => '', 20 | 'html4-trans' => '', 21 | 'html4-frame' => '', 22 | 'mathml1' => '', 23 | 'mathml2' => '', 24 | 'svg10' => '', 25 | 'svg11' => '', 26 | 'svg11-basic' => '', 27 | 'svg11-tiny' => '', 28 | 'xhtml-math-svg-xh' => '', 29 | 'xhtml-math-svg-sh' => '', 30 | 'xhtml-rdfa-1' => '', 31 | 'xhtml-rdfa-2' => '', 32 | ]; 33 | } 34 | -------------------------------------------------------------------------------- /app/Config/Format.php: -------------------------------------------------------------------------------- 1 | 43 | */ 44 | public $formatters = [ 45 | 'application/json' => JSONFormatter::class, 46 | 'application/xml' => XMLFormatter::class, 47 | 'text/xml' => XMLFormatter::class, 48 | ]; 49 | 50 | /** 51 | * -------------------------------------------------------------------------- 52 | * Formatters Options 53 | * -------------------------------------------------------------------------- 54 | * 55 | * Additional Options to adjust default formatters behaviour. 56 | * For each mime type, list the additional options that should be used. 57 | * 58 | * @var array 59 | */ 60 | public $formatterOptions = [ 61 | 'application/json' => JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES, 62 | 'application/xml' => 0, 63 | 'text/xml' => 0, 64 | ]; 65 | 66 | /** 67 | * A Factory method to return the appropriate formatter for the given mime type. 68 | * 69 | * @return FormatterInterface 70 | * 71 | * @deprecated This is an alias of `\CodeIgniter\Format\Format::getFormatter`. Use that instead. 72 | */ 73 | public function getFormatter(string $mime) 74 | { 75 | return Services::format()->getFormatter($mime); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /app/Config/Autoload.php: -------------------------------------------------------------------------------- 1 | SYSTEMPATH, 37 | * 'App' => APPPATH 38 | * ]; 39 | *``` 40 | * 41 | * @var array 42 | */ 43 | public $psr4 = [ 44 | APP_NAMESPACE => APPPATH, // For custom app namespace 45 | 'Config' => APPPATH . 'Config', 46 | ]; 47 | 48 | /** 49 | * ------------------------------------------------------------------- 50 | * Class Map 51 | * ------------------------------------------------------------------- 52 | * The class map provides a map of class names and their exact 53 | * location on the drive. Classes loaded in this manner will have 54 | * slightly faster performance because they will not have to be 55 | * searched for within one or more directories as they would if they 56 | * were being autoloaded through a namespace. 57 | * 58 | * Prototype: 59 | *``` 60 | * $classmap = [ 61 | * 'MyClass' => '/path/to/class/file.php' 62 | * ]; 63 | *``` 64 | * 65 | * @var array 66 | */ 67 | public $classmap = []; 68 | 69 | /** 70 | * ------------------------------------------------------------------- 71 | * Files 72 | * ------------------------------------------------------------------- 73 | * The files array provides a list of paths to __non-class__ files 74 | * that will be autoloaded. This can be useful for bootstrap operations 75 | * or for loading functions. 76 | * 77 | * Prototype: 78 | * ``` 79 | * $files = [ 80 | * '/path/to/my/file.php', 81 | * ]; 82 | * ``` 83 | * 84 | * @var array 85 | */ 86 | public $files = []; 87 | } 88 | -------------------------------------------------------------------------------- /app/Config/Paths.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view 9 | * the LICENSE file that was distributed with this source code. 10 | */ 11 | 12 | /* 13 | *--------------------------------------------------------------- 14 | * Sample file for Preloading 15 | *--------------------------------------------------------------- 16 | * See https://www.php.net/manual/en/opcache.preloading.php 17 | * 18 | * How to Use: 19 | * 1. Set preload::$paths. 20 | * 2. Set opcache.preload in php.ini. 21 | * php.ini: 22 | * opcache.preload=/path/to/preload.php 23 | */ 24 | 25 | // Load the paths config file 26 | require __DIR__ . '/app/Config/Paths.php'; 27 | 28 | // Path to the front controller 29 | define('FCPATH', __DIR__ . DIRECTORY_SEPARATOR . 'public' . DIRECTORY_SEPARATOR); 30 | 31 | /** 32 | * See https://www.php.net/manual/en/function.str-contains.php#126277 33 | */ 34 | if (! function_exists('str_contains')) { 35 | /** 36 | * Polyfill of str_contains() 37 | */ 38 | function str_contains(string $haystack, string $needle): bool 39 | { 40 | return empty($needle) || strpos($haystack, $needle) !== false; 41 | } 42 | } 43 | 44 | class preload 45 | { 46 | /** 47 | * @var array Paths to preload. 48 | */ 49 | private array $paths = [ 50 | [ 51 | 'include' => __DIR__ . '/vendor/codeigniter4/framework/system', 52 | 'exclude' => [ 53 | // Not needed if you don't use them. 54 | '/system/Database/OCI8/', 55 | '/system/Database/Postgre/', 56 | '/system/Database/SQLSRV/', 57 | // Not needed. 58 | '/system/Database/Seeder.php', 59 | '/system/Test/', 60 | '/system/Language/', 61 | '/system/CLI/', 62 | '/system/Commands/', 63 | '/system/Publisher/', 64 | '/system/ComposerScripts.php', 65 | '/Views/', 66 | // Errors occur. 67 | '/system/Config/Routes.php', 68 | '/system/ThirdParty/', 69 | ], 70 | ], 71 | ]; 72 | 73 | public function __construct() 74 | { 75 | $this->loadAutoloader(); 76 | } 77 | 78 | private function loadAutoloader() 79 | { 80 | $paths = new Config\Paths(); 81 | require rtrim($paths->systemDirectory, '\\/ ') . DIRECTORY_SEPARATOR . 'bootstrap.php'; 82 | } 83 | 84 | /** 85 | * Load PHP files. 86 | */ 87 | public function load() 88 | { 89 | foreach ($this->paths as $path) { 90 | $directory = new RecursiveDirectoryIterator($path['include']); 91 | $fullTree = new RecursiveIteratorIterator($directory); 92 | $phpFiles = new RegexIterator( 93 | $fullTree, 94 | '/.+((? $file) { 99 | foreach ($path['exclude'] as $exclude) { 100 | if (str_contains($file[0], $exclude)) { 101 | continue 2; 102 | } 103 | } 104 | 105 | require_once $file[0]; 106 | echo 'Loaded: ' . $file[0] . "\n"; 107 | } 108 | } 109 | } 110 | } 111 | 112 | (new preload())->load(); 113 | -------------------------------------------------------------------------------- /spark: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | 8 | * 9 | * For the full copyright and license information, please view 10 | * the LICENSE file that was distributed with this source code. 11 | */ 12 | 13 | /* 14 | * -------------------------------------------------------------------- 15 | * CodeIgniter command-line tools 16 | * -------------------------------------------------------------------- 17 | * The main entry point into the CLI system and allows you to run 18 | * commands and perform maintenance on your application. 19 | * 20 | * Because CodeIgniter can handle CLI requests as just another web request 21 | * this class mainly acts as a passthru to the framework itself. 22 | */ 23 | 24 | // Refuse to run when called from php-cgi 25 | if (strpos(PHP_SAPI, 'cgi') === 0) { 26 | exit("The cli tool is not supported when running php-cgi. It needs php-cli to function!\n\n"); 27 | } 28 | 29 | // Check PHP version. 30 | $minPhpVersion = '7.4'; // If you update this, don't forget to update `public/index.php`. 31 | if (version_compare(PHP_VERSION, $minPhpVersion, '<')) { 32 | $message = sprintf( 33 | 'Your PHP version must be %s or higher to run CodeIgniter. Current version: %s', 34 | $minPhpVersion, 35 | PHP_VERSION 36 | ); 37 | 38 | exit($message); 39 | } 40 | 41 | // We want errors to be shown when using it from the CLI. 42 | error_reporting(-1); 43 | ini_set('display_errors', '1'); 44 | 45 | /** 46 | * @var bool 47 | * 48 | * @deprecated No longer in use. `CodeIgniter` has `$context` property. 49 | */ 50 | define('SPARKED', true); 51 | 52 | // Path to the front controller 53 | define('FCPATH', __DIR__ . DIRECTORY_SEPARATOR . 'public' . DIRECTORY_SEPARATOR); 54 | 55 | // Ensure the current directory is pointing to the front controller's directory 56 | chdir(FCPATH); 57 | 58 | /* 59 | *--------------------------------------------------------------- 60 | * BOOTSTRAP THE APPLICATION 61 | *--------------------------------------------------------------- 62 | * This process sets up the path constants, loads and registers 63 | * our autoloader, along with Composer's, loads our constants 64 | * and fires up an environment-specific bootstrapping. 65 | */ 66 | 67 | // Load our paths config file 68 | // This is the line that might need to be changed, depending on your folder structure. 69 | require FCPATH . '../app/Config/Paths.php'; 70 | // ^^^ Change this line if you move your application folder 71 | 72 | $paths = new Config\Paths(); 73 | 74 | // Location of the framework bootstrap file. 75 | require rtrim($paths->systemDirectory, '\\/ ') . DIRECTORY_SEPARATOR . 'bootstrap.php'; 76 | 77 | // Load environment settings from .env files into $_SERVER and $_ENV 78 | require_once SYSTEMPATH . 'Config/DotEnv.php'; 79 | (new CodeIgniter\Config\DotEnv(ROOTPATH))->load(); 80 | 81 | // Grab our CodeIgniter 82 | $app = Config\Services::codeigniter(); 83 | $app->initialize(); 84 | $app->setContext('spark'); 85 | 86 | // Grab our Console 87 | $console = new CodeIgniter\CLI\Console($app); 88 | 89 | // Show basic information before we do anything else. 90 | if (is_int($suppress = array_search('--no-header', $_SERVER['argv'], true))) { 91 | unset($_SERVER['argv'][$suppress]); // @codeCoverageIgnore 92 | $suppress = true; 93 | } 94 | 95 | $console->showHeader($suppress); 96 | 97 | // fire off the command in the main framework. 98 | $response = $console->run(); 99 | 100 | if ($response->getStatusCode() >= 300) { 101 | exit($response->getStatusCode()); 102 | } 103 | -------------------------------------------------------------------------------- /app/Config/Toolbar.php: -------------------------------------------------------------------------------- 1 | ` element. 81 | * 82 | * Will default to self if not overridden 83 | * 84 | * @var string|string[]|null 85 | */ 86 | public $baseURI; 87 | 88 | /** 89 | * Lists the URLs for workers and embedded frame contents 90 | * 91 | * @var string|string[] 92 | */ 93 | public $childSrc = 'self'; 94 | 95 | /** 96 | * Limits the origins that you can connect to (via XHR, 97 | * WebSockets, and EventSource). 98 | * 99 | * @var string|string[] 100 | */ 101 | public $connectSrc = 'self'; 102 | 103 | /** 104 | * Specifies the origins that can serve web fonts. 105 | * 106 | * @var string|string[] 107 | */ 108 | public $fontSrc; 109 | 110 | /** 111 | * Lists valid endpoints for submission from `
` tags. 112 | * 113 | * @var string|string[] 114 | */ 115 | public $formAction = 'self'; 116 | 117 | /** 118 | * Specifies the sources that can embed the current page. 119 | * This directive applies to ``, `