From 7473414d1058847dc5ea214b852b1c514e60c1d2 Mon Sep 17 00:00:00 2001 From: mech Date: Sun, 22 Dec 2019 16:23:47 +0100 Subject: [PATCH 1/8] Set up the docker-compose env --- Dockerfile-php | 3 ++ db.sql | 53 ++++++++++++++++++++ docker-compose.yml | 25 ++++++++++ index.php | 121 +++++++++++++++++++++++++++++++++++++++++++++ site.conf | 26 ++++++++++ 5 files changed, 228 insertions(+) create mode 100644 Dockerfile-php create mode 100644 db.sql create mode 100644 docker-compose.yml create mode 100644 index.php create mode 100644 site.conf diff --git a/Dockerfile-php b/Dockerfile-php new file mode 100644 index 00000000..7adc731e --- /dev/null +++ b/Dockerfile-php @@ -0,0 +1,3 @@ +FROM php:7.3-fpm + +RUN docker-php-ext-install mysqli && docker-php-ext-enable mysqli 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..d1bb9701 --- /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: motoszkola-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/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; + } + +} From ed6efd708d9f34361a7eb7da3d626260c2190cce Mon Sep 17 00:00:00 2001 From: mech Date: Sun, 22 Dec 2019 16:24:53 +0100 Subject: [PATCH 2/8] Init the cookie salt --- application/bootstrap.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/bootstrap.php b/application/bootstrap.php index 1f3dc57d..a377e091 100644 --- a/application/bootstrap.php +++ b/application/bootstrap.php @@ -148,7 +148,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 From 2ed4360683c00b66f6594f2253518479025e2b96 Mon Sep 17 00:00:00 2001 From: mech Date: Sun, 22 Dec 2019 16:30:02 +0100 Subject: [PATCH 3/8] Fixing the "Class 'Profiler' not found" fatal --- application/bootstrap.php | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/application/bootstrap.php b/application/bootstrap.php index a377e091..6cf16947 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. From 0b4e9ec4e8dfff39640b57d87bf6623c02f19886 Mon Sep 17 00:00:00 2001 From: mech Date: Sun, 22 Dec 2019 16:38:06 +0100 Subject: [PATCH 4/8] Enable the orm-based auth actions --- application/bootstrap.php | 6 +-- application/classes/Controller/Welcome.php | 48 +++++++++++++++++++- application/config/auth.php | 12 +++++ application/config/database.php | 53 ++++++++++++++++++++++ application/config/url.php | 8 ++++ 5 files changed, 123 insertions(+), 4 deletions(-) create mode 100755 application/config/auth.php create mode 100755 application/config/database.php create mode 100644 application/config/url.php diff --git a/application/bootstrap.php b/application/bootstrap.php index 6cf16947..b9ad7fc9 100644 --- a/application/bootstrap.php +++ b/application/bootstrap.php @@ -141,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 diff --git a/application/classes/Controller/Welcome.php b/application/classes/Controller/Welcome.php index 58dcd4de..cc4ccc30 100644 --- a/application/classes/Controller/Welcome.php +++ b/application/classes/Controller/Welcome.php @@ -2,9 +2,55 @@ 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_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!'); + } else { + $this->response->body('hello, ' . $user->username); + } + + } + + 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', + ], +]; From f27a4e74a47833c6241d7c4fa25f7f3cbb67ca4c Mon Sep 17 00:00:00 2001 From: mech Date: Sun, 22 Dec 2019 16:44:03 +0100 Subject: [PATCH 5/8] Workaround(s) for the auth user deserialization bug --- modules/orm/classes/Kohana/ORM.php | 3 +++ modules/orm/classes/Model/Auth/User.php | 4 ++++ 2 files changed, 7 insertions(+) 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(); } } From 4e734d2646030a23e1c399c8bd5ee54c546ab315 Mon Sep 17 00:00:00 2001 From: mech Date: Sun, 22 Dec 2019 16:49:08 +0100 Subject: [PATCH 6/8] login/logout links on the welcome page --- application/classes/Controller/Welcome.php | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/application/classes/Controller/Welcome.php b/application/classes/Controller/Welcome.php index cc4ccc30..0e837e81 100644 --- a/application/classes/Controller/Welcome.php +++ b/application/classes/Controller/Welcome.php @@ -2,7 +2,8 @@ class Controller_Welcome extends Controller { - public function action_login() { + public function action_login() + { $status = Auth::instance()->login('newadmin' ,'somepass', true); if ($status) { $this->redirect('welcome/index'); @@ -11,6 +12,12 @@ public function action_login() { } } + public function action_logout() + { + Auth::instance()->logout(TRUE); + $this->redirect('welcome/index'); + } + public function action_index() { $user = null; @@ -20,9 +27,9 @@ public function action_index() echo $e."
"; } if (!$user) { - $this->response->body('hello, anon user!'); + $this->response->body('hello, anon user!
login
register user'); } else { - $this->response->body('hello, ' . $user->username); + $this->response->body('hello, ' . $user->username . '.
logout'); } } From 92c90cb618accdd1dfc7ec511a1853e5bcbc8204 Mon Sep 17 00:00:00 2001 From: mech Date: Sun, 22 Dec 2019 16:52:43 +0100 Subject: [PATCH 7/8] whitespaces --- application/classes/Controller/Welcome.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/application/classes/Controller/Welcome.php b/application/classes/Controller/Welcome.php index 0e837e81..ae7b7585 100644 --- a/application/classes/Controller/Welcome.php +++ b/application/classes/Controller/Welcome.php @@ -20,7 +20,7 @@ public function action_logout() public function action_index() { - $user = null; + $user = null; try { $user = Auth::instance()->get_user(); } catch (Exception $e) { @@ -31,12 +31,11 @@ public function action_index() } else { $this->response->body('hello, ' . $user->username . '.
logout'); } - } public function action_register() { - $user = ORM::factory('User'); + $user = ORM::factory('User'); $user->where('username', '=', 'newadmin')->find(); if (!$user->loaded()) { $user = ORM::factory('user'); @@ -57,7 +56,6 @@ public function action_register() $this->response->body('user exists'); } - } } // End Welcome From cdcd6fb6e9e05eac7538c181a42bd758095ff74f Mon Sep 17 00:00:00 2001 From: mech Date: Mon, 23 Dec 2019 22:11:50 +0100 Subject: [PATCH 8/8] Switch do php:7-fpm --- Dockerfile-php | 2 +- docker-compose.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile-php b/Dockerfile-php index 7adc731e..fed9ae3a 100644 --- a/Dockerfile-php +++ b/Dockerfile-php @@ -1,3 +1,3 @@ -FROM php:7.3-fpm +FROM php:7-fpm RUN docker-php-ext-install mysqli && docker-php-ext-enable mysqli diff --git a/docker-compose.yml b/docker-compose.yml index d1bb9701..7663aa84 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -17,7 +17,7 @@ services: - .:/app - ./site.conf:/etc/nginx/conf.d/default.conf:ro php: - image: motoszkola-php + image: custom-php build: context: . dockerfile: Dockerfile-php