From 8a8f0e505dc9d40261c8e500fc0e7564a0beda50 Mon Sep 17 00:00:00 2001 From: Jordan Doyle Date: Thu, 06 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(-) diff --git a/config/wordpress.php b/config/wordpress.php index d9f41bc..e88ee69 100644 --- a/config/wordpress.php +++ a/config/wordpress.php @@ -9,4 +9,11 @@ '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 100644 --- /dev/null +++ a/src/Guards/WordpressGuard.php @@ -1,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 +++ a/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'; @@ -22,5 +26,15 @@ public function posts() { 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 +++ a/src/Providers/WordpressServiceProvider.php @@ -1,9 +1,11 @@ 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) @@ -115,6 +130,29 @@ define('WP_CONTENT_DIR', $this->app->basePath() . DIRECTORY_SEPARATOR . 'public/content'); define('WP_CONTENT_URL', $this->app->make(UrlGenerator::class)->to('content')); + } + + /** + * 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')); + } + } } /** diff --git a/src/Routing/Route.php b/src/Routing/Route.php new file mode 100644 index 0000000..cd50c6e 100644 --- /dev/null +++ a/src/Routing/Route.php @@ -1,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 +++ a/src/Routing/Routing.php @@ -1,8 +1,9 @@