diff --git a/Dockerfile-php b/Dockerfile-php
new file mode 100644
index 00000000..fed9ae3a
--- /dev/null
+++ b/Dockerfile-php
@@ -0,0 +1,3 @@
+FROM php:7-fpm
+
+RUN docker-php-ext-install mysqli && docker-php-ext-enable mysqli
diff --git a/application/bootstrap.php b/application/bootstrap.php
index 1f3dc57d..b9ad7fc9 100644
--- a/application/bootstrap.php
+++ b/application/bootstrap.php
@@ -110,9 +110,21 @@
* - boolean caching enable or disable internal caching FALSE
* - boolean expose set the X-Powered-By header FALSE
*/
-Kohana::init([
+$_settings = [
'base_url' => '/',
-]);
+ 'errors' => FALSE,
+];
+// Load the Profiler class when profiling is enabled
+// otherwise I get the following error:
+/*
+ Fatal error: Uncaught Error: Class 'Profiler' not found in /app/system/classes/Kohana/Core.php:598 Stack trace: #0 /app/system/classes/Kohana/Core.php(427): Kohana_Core::find_file('classes', 'Kohana/Profiler') #1 [internal function]: Kohana_Core::auto_load('Kohana_Profiler') #2 /app/system/classes/Profiler.php(3): spl_autoload_call('Kohana_Profiler') #3 /app/system/classes/Kohana/Core.php(430): require('/app/system/cla...') #4 [internal function]: Kohana_Core::auto_load('Profiler') #5 /app/system/classes/Kohana/Request/Client/Internal.php(60): spl_autoload_call('Profiler') #6 /app/system/classes/Kohana/Request/Client.php(114): Kohana_Request_Client_Internal->execute_request(Object(Request), Object(Response)) #7 /app/system/classes/Kohana/Request.php(1000): Kohana_Request_Client->execute(Object(Request)) #8 /app/index.php(118): Kohana_Request->execute() #9 {main} thrown in /app/system/classes/Kohana/Core.php on line 598
+ */
+if (!isset($_settings['profile']) || !empty($_settings['profile']))
+{
+ require SYSPATH.'classes/Kohana/Profiler'.EXT;
+ require SYSPATH.'classes/Profiler'.EXT;
+}
+Kohana::init($_settings);
/**
* Attach the file write to logging. Multiple writers are supported.
@@ -129,13 +141,13 @@
*/
Kohana::modules([
// 'encrypt' => MODPATH.'encrypt', // Encryption supprt
- // 'auth' => MODPATH.'auth', // Basic authentication
+ 'auth' => MODPATH.'auth', // Basic authentication
// 'cache' => MODPATH.'cache', // Caching with multiple backends
// 'codebench' => MODPATH.'codebench', // Benchmarking tool
- // 'database' => MODPATH.'database', // Database access
+ 'database' => MODPATH.'database', // Database access
// 'image' => MODPATH.'image', // Image manipulation
// 'minion' => MODPATH.'minion', // CLI Tasks
- // 'orm' => MODPATH.'orm', // Object Relationship Mapping
+ 'orm' => MODPATH.'orm', // Object Relationship Mapping
// 'pagination' => MODPATH.'pagination', // Pagination
// 'unittest' => MODPATH.'unittest', // Unit testing
// 'userguide' => MODPATH.'userguide', // User guide and API documentation
@@ -148,7 +160,7 @@
* If you have not defined a cookie salt in your Cookie class then
* uncomment the line below and define a preferrably long salt.
*/
-// Cookie::$salt = NULL;
+Cookie::$salt = '2139821639u2yhrd3912u';
/**
* Cookie HttpOnly directive
* If set to true, disallows cookies to be accessed from JavaScript
diff --git a/application/classes/Controller/Welcome.php b/application/classes/Controller/Welcome.php
index 58dcd4de..ae7b7585 100644
--- a/application/classes/Controller/Welcome.php
+++ b/application/classes/Controller/Welcome.php
@@ -2,9 +2,60 @@
class Controller_Welcome extends Controller {
+ public function action_login()
+ {
+ $status = Auth::instance()->login('newadmin' ,'somepass', true);
+ if ($status) {
+ $this->redirect('welcome/index');
+ } else {
+ $this->response->body('login failed!');
+ }
+ }
+
+ public function action_logout()
+ {
+ Auth::instance()->logout(TRUE);
+ $this->redirect('welcome/index');
+ }
+
public function action_index()
{
- $this->response->body('hello, world!');
+ $user = null;
+ try {
+ $user = Auth::instance()->get_user();
+ } catch (Exception $e) {
+ echo $e."
";
+ }
+ if (!$user) {
+ $this->response->body('hello, anon user!
login
register user');
+ } else {
+ $this->response->body('hello, ' . $user->username . '.
logout');
+ }
+ }
+
+ public function action_register()
+ {
+ $user = ORM::factory('User');
+ $user->where('username', '=', 'newadmin')->find();
+ if (!$user->loaded()) {
+ $user = ORM::factory('user');
+ $user->username = 'newadmin';
+ $user->password = 'somepass';
+ $user->email = 'foor@bar.org';
+ try{
+ $user->save();
+ $user->add('roles', ORM::factory('Role')->where('name', '=', 'login')->find());
+ $user->save();
+ $this->response->body('user created');
+ }
+ catch(ORM_Validation_Exception $e){
+ var_dump($e->errors());
+ die();
+ }
+ } else {
+ $this->response->body('user exists');
+
+ }
}
} // End Welcome
diff --git a/application/config/auth.php b/application/config/auth.php
new file mode 100755
index 00000000..5b286746
--- /dev/null
+++ b/application/config/auth.php
@@ -0,0 +1,12 @@
+ 'ORM',
+ 'hash_method' => 'sha256',
+ 'hash_key' => '123598123568612638',
+ 'lifetime' => 1209600,
+ 'session_type' => Session::$default, // native
+ 'session_key' => 'auth_user',
+ 'users' => []
+);
diff --git a/application/config/database.php b/application/config/database.php
new file mode 100755
index 00000000..5cee94fc
--- /dev/null
+++ b/application/config/database.php
@@ -0,0 +1,53 @@
+ array
+ (
+ 'type' => 'MySQLi',
+ 'connection' => array(
+ /**
+ * The following options are available for MySQL:
+ *
+ * string hostname
+ * string username
+ * string password
+ * boolean persistent
+ * string database
+ *
+ * Ports and sockets may be appended to the hostname.
+ */
+ 'hostname' => 'mysql',
+ 'username' => 'root',
+ 'password' => 'somepass',
+ 'persistent' => FALSE,
+ 'database' => 'koseven',
+ ),
+ 'table_prefix' => '',
+ 'charset' => 'utf8',
+ 'caching' => FALSE,
+ 'profiling' => TRUE,
+ ),
+ 'alternate' => array(
+ 'type' => 'pdo',
+ 'connection' => array(
+ /**
+ * The following options are available for PDO:
+ *
+ * string dsn
+ * string username
+ * string password
+ * boolean persistent
+ * string identifier
+ */
+ 'dsn' => 'mysql:host=mysql;dbname=koseven',
+ 'username' => 'root',
+ 'password' => 'somepass',
+ 'persistent' => FALSE,
+ ),
+ 'table_prefix' => '',
+ 'charset' => 'utf8',
+ 'caching' => FALSE,
+ 'profiling' => TRUE,
+ ),
+);
diff --git a/application/config/url.php b/application/config/url.php
new file mode 100644
index 00000000..bd8628e3
--- /dev/null
+++ b/application/config/url.php
@@ -0,0 +1,8 @@
+ [
+ 'localhost:8080',
+ ],
+];
diff --git a/db.sql b/db.sql
new file mode 100644
index 00000000..9f3e990b
--- /dev/null
+++ b/db.sql
@@ -0,0 +1,53 @@
+CREATE DATABASE IF NOT EXISTS `koseven` DEFAULT CHARACTER SET utf8 COLLATE utf8_polish_ci;
+USE `koseven`;
+
+CREATE TABLE IF NOT EXISTS `roles` (
+ `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
+ `name` varchar(32) NOT NULL,
+ `description` varchar(255) NOT NULL,
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `uniq_name` (`name`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+INSERT INTO `roles` (`id`, `name`, `description`) VALUES(1, 'login', 'Login privileges, granted after account confirmation');
+INSERT INTO `roles` (`id`, `name`, `description`) VALUES(2, 'admin', 'Administrative user, has access to everything.');
+
+CREATE TABLE IF NOT EXISTS `roles_users` (
+ `user_id` int(10) UNSIGNED NOT NULL,
+ `role_id` int(10) UNSIGNED NOT NULL,
+ PRIMARY KEY (`user_id`,`role_id`),
+ KEY `fk_role_id` (`role_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+CREATE TABLE IF NOT EXISTS `users` (
+ `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
+ `email` varchar(254) NOT NULL,
+ `username` varchar(32) NOT NULL DEFAULT '',
+ `password` varchar(64) NOT NULL,
+ `logins` int(10) UNSIGNED NOT NULL DEFAULT '0',
+ `last_login` int(10) UNSIGNED,
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `uniq_username` (`username`),
+ UNIQUE KEY `uniq_email` (`email`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+CREATE TABLE IF NOT EXISTS `user_tokens` (
+ `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
+ `user_id` int(11) UNSIGNED NOT NULL,
+ `user_agent` varchar(40) NOT NULL,
+ `token` varchar(40) NOT NULL,
+ `created` int(10) UNSIGNED NOT NULL,
+ `expires` int(10) UNSIGNED NOT NULL,
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `uniq_token` (`token`),
+ KEY `fk_user_id` (`user_id`),
+ KEY `expires` (`expires`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+ALTER TABLE `roles_users`
+ ADD CONSTRAINT `roles_users_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE,
+ ADD CONSTRAINT `roles_users_ibfk_2` FOREIGN KEY (`role_id`) REFERENCES `roles` (`id`) ON DELETE CASCADE;
+
+ALTER TABLE `user_tokens`
+ ADD CONSTRAINT `user_tokens_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE;
+
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 00000000..7663aa84
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,25 @@
+version: '2'
+
+services:
+ mysql:
+ image: mysql:5.6.45
+ ports:
+ - "3306:3306"
+ volumes:
+ - ./db.sql:/docker-entrypoint-initdb.d/dump.sql
+ environment:
+ - MYSQL_ROOT_PASSWORD=somepass
+ web:
+ image: nginx:latest
+ ports:
+ - "8080:80"
+ volumes:
+ - .:/app
+ - ./site.conf:/etc/nginx/conf.d/default.conf:ro
+ php:
+ image: custom-php
+ build:
+ context: .
+ dockerfile: Dockerfile-php
+ volumes:
+ - .:/app
diff --git a/index.php b/index.php
new file mode 100644
index 00000000..f302ee11
--- /dev/null
+++ b/index.php
@@ -0,0 +1,121 @@
+execute();
+}
+else
+{
+ /**
+ * Execute the main request. A source of the URI can be passed, eg: $_SERVER['PATH_INFO'].
+ * If no source is specified, the URI will be automatically detected.
+ */
+ echo Request::factory(TRUE, [], FALSE)
+ ->execute()
+ ->send_headers(TRUE)
+ ->body();
+}
diff --git a/modules/orm/classes/Kohana/ORM.php b/modules/orm/classes/Kohana/ORM.php
index c1ebd6d1..eb6efca9 100644
--- a/modules/orm/classes/Kohana/ORM.php
+++ b/modules/orm/classes/Kohana/ORM.php
@@ -573,6 +573,9 @@ public function serialize()
// Store only information about the object
foreach (['_primary_key_value', '_object', '_changed', '_loaded', '_saved', '_sorting', '_original_values'] as $var)
{
+ // this causes (de)serialization issues when an object is used in both _object and _original_values vars
+ // it this case if an object is shared between those two, it will be serialized in _original_values as a reference
+ // and cause deserialization issues.php. $data[$var] = serialize($this->{$var}) would be a dirty workaround here.
$data[$var] = $this->{$var};
}
diff --git a/modules/orm/classes/Model/Auth/User.php b/modules/orm/classes/Model/Auth/User.php
index c192b859..67bf52d7 100644
--- a/modules/orm/classes/Model/Auth/User.php
+++ b/modules/orm/classes/Model/Auth/User.php
@@ -92,6 +92,10 @@ public function complete_login()
// Save the user
$this->update();
+
+ // reload the user so the logins is not referencing the Database_Expression anymore
+ // otherwise it will be serialized to a json in a session and lead to errors
+ $this->reload();
}
}
diff --git a/site.conf b/site.conf
new file mode 100644
index 00000000..a465e7be
--- /dev/null
+++ b/site.conf
@@ -0,0 +1,26 @@
+server {
+ index index.php index.html;
+ server_name localhost;
+ error_log /dev/stdout info;
+ access_log /dev/stdout;
+ root /app;
+ index index.php;
+
+ rewrite_log on;
+
+
+ location / {
+ expires off;
+ try_files $uri $uri/ /index.php?$uri&$args;
+ }
+
+ location ~ .*\.(php|php5)?$ {
+ try_files $uri =404;
+ fastcgi_pass php:9000;
+ fastcgi_index index.php;
+ include fastcgi_params;
+ fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
+ fastcgi_param PATH_INFO $fastcgi_path_info;
+ }
+
+}