From 8a8f0e505dc9d40261c8e500fc0e7564a0beda50 Mon Sep 17 00:00:00 2001 From: Jordan Doyle Date: Thu, 6 Oct 2016 15:58:50 +0100 Subject: [PATCH] Multisite & laravel -> wordpress authentication integration --- config/wordpress.php | 7 +++++++ src/Guards/WordpressGuard.php | 205 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/Models/User.php | 16 +++++++++++++++- src/Providers/WordpressServiceProvider.php | 38 ++++++++++++++++++++++++++++++++++++++ src/Routing/Route.php | 40 ++++++++++++++++++++++++++++++++++++++++ src/Routing/Routing.php | 1 + src/Support/Wordpress.php | 4 +++- 7 files changed, 309 insertions(+), 2 deletions(-) create mode 100644 src/Guards/WordpressGuard.php create mode 100644 src/Routing/Route.php diff --git a/config/wordpress.php b/config/wordpress.php index d9f41bc..e88ee69 100644 --- a/config/wordpress.php +++ b/config/wordpress.php @@ -9,4 +9,11 @@ return [ 'secure_auth_salt' => env('SECURE_AUTH_SALT'), 'logged_in_salt' => env('LOGGED_IN_SALT'), 'nonce_salt' => env('NONCE_SALT'), + 'wp_allow_multisite' => env('WP_ALLOW_MULTISITE'), + 'multisite' => env('MULTISITE'), + 'subdomain_install' => env('SUBDOMAIN_INSTALL'), + 'domain_current_site' => env('DOMAIN_CURRENT_SITE'), + 'path_current_site' => env('PATH_CURRENT_SITE'), + 'site_id_current_site' => env('SITE_ID_CURRENT_SITE'), + 'blog_id_current_site' => env('BLOG_ID_CURRENT_SITE'), ]; diff --git a/src/Guards/WordpressGuard.php b/src/Guards/WordpressGuard.php new file mode 100644 index 0000000..410fde7 --- /dev/null +++ b/src/Guards/WordpressGuard.php @@ -0,0 +1,205 @@ + + */ +class WordpressGuard implements StatefulGuard +{ + use GuardHelpers; + + /** + * Get the last user we attempted to login as. + * + * @var User + */ + private $lastAttempted = null; + + /** + * Determine if the current user is authenticated. + * + * @return bool + */ + public function check() + { + return is_user_logged_in(); + } + + /** + * Get the currently authenticated user. + * + * @return \Illuminate\Contracts\Auth\Authenticatable|null + */ + public function user() + { + // If we've already retrieved the user for the current request we can just + // return it back immediately. We do not want to fetch the user data on + // every call to this method because that would be tremendously slow. + if (!is_null($this->user)) { + return $this->user; + } + + return $this->user = ($this->check() ? User::find(get_current_user_id()) : null); + } + + /** + * Validate a user's credentials. + * + * @param array $credentials + * @return bool + */ + public function validate(array $credentials = []) + { + $user = wp_authenticate($credentials['username'], $credentials['password']); + + $this->lastAttempted = User::find($user->ID); + + return !($user instanceof WP_Error); + } + + /** + * Attempt to authenticate a user using the given credentials. + * + * @param array $credentials + * @param bool $remember + * @param bool $login + * @return bool + */ + public function attempt(array $credentials = [], $remember = false, $login = true) + { + $validate = $this->validate($credentials); + + if (!$login) { + return $validate; + } + + $user = $this->lastAttempted; + + // check if we should use a secure cookie + wp_set_auth_cookie($user->ID, $credentials['remember'], Request::secure()); + Action::trigger('wp_login', $user->user_login, $user); + + $this->setUser($user); + + return true; + } + + /** + * Log a user into the application without sessions or cookies. + * + * @param array $credentials + * @return bool + */ + public function once(array $credentials = []) + { + if ($this->validate($credentials)) { + $this->setUser($this->lastAttempted); + return true; + } + + return false; + } + + /** + * Log a user into the application. + * + * @param \Illuminate\Contracts\Auth\Authenticatable $user + * @param bool $remember + * @return void + */ + public function login(Authenticatable $user, $remember = false) + { + wp_set_auth_cookie($user->ID, $remember); + Action::trigger('wp_login', $user->user_login, get_userdata($user->ID)); + wp_set_current_user($user->ID); + + $this->user = $user; + } + + /** + * Log the given user ID into the application. + * + * @param mixed $id + * @param bool $remember + * @return \Illuminate\Contracts\Auth\Authenticatable|bool + */ + public function loginUsingId($id, $remember = false) + { + $user = User::find($id); + + if (!$user) { + return false; + } + + wp_set_auth_cookie($user->ID, $remember); + Action::trigger('wp_login', $user->user_login, get_userdata($user->ID)); + wp_set_current_user($user->ID); + + return $this->user = $user; + } + + /** + * Log the given user ID into the application without sessions or cookies. + * + * @param mixed $id + * @return bool + */ + public function onceUsingId($id) + { + $user = User::find($id); + + if (!$user) { + return false; + } + + wp_set_current_user($id); + + return $this->user = $user; + } + + /** + * Determine if the user was authenticated via "remember me" cookie. + * + * @return bool + */ + public function viaRemember() + { + return Request::hasCookie(Request::secure() ? SECURE_AUTH_COOKIE : AUTH_COOKIE); + } + + /** + * Log the user out of the application. + * + * @return void + */ + public function logout() + { + wp_logout(); + $this->user = null; + } + + /** + * Set the current user. + * + * @param \Illuminate\Contracts\Auth\Authenticatable $user + * @return $this + */ + public function setUser(Authenticatable $user) + { + wp_set_current_user($user->ID); + $this->user = $user; + + return $this; + } +} diff --git a/src/Models/User.php b/src/Models/User.php index 80a82f5..98ed007 100644 --- a/src/Models/User.php +++ b/src/Models/User.php @@ -1,6 +1,8 @@ */ -class User extends Model +class User extends Model implements AuthenticatableContract { + use Authenticatable; + public $table = DB_PREFIX . 'users'; public $primaryKey = 'ID'; @@ -23,4 +27,14 @@ class User extends Model { return $this->hasMany(self::class, 'post_author'); } + + /** + * Get the password for the user. + * + * @return string + */ + public function getAuthPassword() + { + return $this->user_pass; + } } diff --git a/src/Providers/WordpressServiceProvider.php b/src/Providers/WordpressServiceProvider.php index 9aff474..183b476 100644 --- a/src/Providers/WordpressServiceProvider.php +++ b/src/Providers/WordpressServiceProvider.php @@ -2,8 +2,10 @@ namespace Koselig\Providers; use Illuminate\Contracts\Routing\UrlGenerator; +use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\DB; use Illuminate\Support\ServiceProvider; +use Koselig\Guards\WordpressGuard; use Koselig\Support\Action; /** @@ -39,6 +41,18 @@ class WordpressServiceProvider extends ServiceProvider } /** + * Register the Wordpress authentication services. + * + * @return void + */ + public function boot() + { + Auth::extend('wordpress', function ($app, $name, array $config) { + return new WordpressGuard(Auth::createUserProvider($config['provider'])); + }); + } + + /** * Set up the configuration values that wp-config.php * does. Use all the values out of .env instead. * @@ -57,6 +71,7 @@ class WordpressServiceProvider extends ServiceProvider $this->setDatabaseConstants($table_prefix); $this->setAuthenticationConstants(); $this->setLocationConstants(); + $this->setMultisiteConstants(); if ($this->app->runningInConsole()) { // allow wordpress to run, even when running from console (ie. artisan compiling) @@ -118,6 +133,29 @@ class WordpressServiceProvider extends ServiceProvider } /** + * Set up constants that will allow the user to use a multisite install of Wordpress. + */ + private function setMultisiteConstants() + { + $multisite = $this->app->make('config')->get('wordpress.wp_allow_multisite'); + + if ($multisite) { + define('WP_ALLOW_MULTISITE', $multisite); + + $enabled = $this->app->make('config')->get('wordpress.multisite'); + + if ($enabled) { + define('MULTISITE', $enabled); + define('SUBDOMAIN_INSTALL', $this->app->make('config')->get('wordpress.subdomain_install')); + define('DOMAIN_CURRENT_SITE', $this->app->make('config')->get('wordpress.domain_current_site')); + define('PATH_CURRENT_SITE', $this->app->make('config')->get('wordpress.path_current_site')); + define('SITE_ID_CURRENT_SITE', $this->app->make('config')->get('wordpress.site_id_current_site')); + define('BLOG_ID_CURRENT_SITE', $this->app->make('config')->get('wordpress.blog_id_current_site')); + } + } + } + + /** * Wordpress core hooks needed for the main functionality of * Koselig. * diff --git a/src/Routing/Route.php b/src/Routing/Route.php new file mode 100644 index 0000000..cd50c6e --- /dev/null +++ b/src/Routing/Route.php @@ -0,0 +1,40 @@ + + */ +class Route extends LaravelRoute +{ + /** + * Determine if the route matches given request. + * + * @param \Illuminate\Http\Request $request + * @param bool $includingMethod + * @return bool + */ + public function matches(Request $request, $includingMethod = true) + { + $this->compileRoute(); + + foreach ($this->getValidators() as $validator) { + if (!$includingMethod && $validator instanceof MethodValidator) { + continue; + } + + if (!$validator->matches($this, $request)) { + return false; + } + } + + return true; + } +} diff --git a/src/Routing/Routing.php b/src/Routing/Routing.php index 1ff2d70..0f39c77 100644 --- a/src/Routing/Routing.php +++ b/src/Routing/Routing.php @@ -3,6 +3,7 @@ namespace Koselig\Routing; use Illuminate\Container\Container; use Illuminate\Support\Facades\Route; +use Koselig\Routing\Route as KoseligRoute; class Routing { diff --git a/src/Support/Wordpress.php b/src/Support/Wordpress.php index 5ab59b0..8b18435 100644 --- a/src/Support/Wordpress.php +++ b/src/Support/Wordpress.php @@ -94,7 +94,9 @@ class Wordpress } /** - * Get the current logged in user. + * Get the current logged in user. Generally, you shouldn't be using this + * function and should instead be using Auth::user() from Laravel to get + * the current logged in Wordpress user. * * @return \WP_User */ -- libgit2 1.7.2