]> BookStack Code Mirror - bookstack/commitdiff
Added login/register theme events
authorDan Brown <redacted>
Fri, 19 Mar 2021 21:54:50 +0000 (21:54 +0000)
committerDan Brown <redacted>
Fri, 19 Mar 2021 21:54:50 +0000 (21:54 +0000)
12 files changed:
app/Auth/Access/Guards/LdapSessionGuard.php
app/Auth/Access/RegistrationService.php
app/Auth/Access/Saml2Service.php
app/Auth/Access/SocialAuthService.php
app/Http/Controllers/Auth/ConfirmEmailController.php
app/Http/Controllers/Auth/LoginController.php
app/Http/Controllers/Auth/RegisterController.php
app/Http/Controllers/Auth/SocialController.php
app/Http/Controllers/Auth/UserInviteController.php
app/Theming/ThemeEvents.php
tests/Auth/SocialAuthTest.php
tests/ThemeTest.php

index d761a30e66b366b66be41b204b1d08223824ff22..cabbfbbcbb7ac17065f0446fec76af95d9a362a0 100644 (file)
@@ -5,14 +5,12 @@ namespace BookStack\Auth\Access\Guards;
 use BookStack\Auth\Access\LdapService;
 use BookStack\Auth\Access\RegistrationService;
 use BookStack\Auth\User;
-use BookStack\Auth\UserRepo;
 use BookStack\Exceptions\LdapException;
 use BookStack\Exceptions\LoginAttemptException;
 use BookStack\Exceptions\LoginAttemptEmailNeededException;
 use BookStack\Exceptions\UserRegistrationException;
 use Illuminate\Contracts\Auth\UserProvider;
 use Illuminate\Contracts\Session\Session;
-use Illuminate\Support\Facades\Hash;
 use Illuminate\Support\Str;
 
 class LdapSessionGuard extends ExternalBaseSessionGuard
index 9070d12415543410fff1cc3fa275a15af867f27c..68b17771d628552fe57a1d40fe7301774d43adb9 100644 (file)
@@ -6,6 +6,8 @@ use BookStack\Auth\User;
 use BookStack\Auth\UserRepo;
 use BookStack\Exceptions\UserRegistrationException;
 use BookStack\Facades\Activity;
+use BookStack\Facades\Theme;
+use BookStack\Theming\ThemeEvents;
 use Exception;
 
 class RegistrationService
@@ -71,6 +73,7 @@ class RegistrationService
         }
 
         Activity::add(ActivityType::AUTH_REGISTER, $socialAccount ?? $newUser);
+        Theme::dispatch(ThemeEvents::AUTH_REGISTER, $socialAccount ? $socialAccount->driver : auth()->getDefaultDriver(), $newUser);
 
         // Start email confirmation flow if required
         if ($this->emailConfirmationService->confirmationRequired() && !$emailConfirmed) {
index 0316ff976e4623e222ac69cdcf956f8efab55334..105853997cd4d939c3fefe66678915dea89bdaa9 100644 (file)
@@ -6,6 +6,8 @@ use BookStack\Exceptions\JsonDebugException;
 use BookStack\Exceptions\SamlException;
 use BookStack\Exceptions\UserRegistrationException;
 use BookStack\Facades\Activity;
+use BookStack\Facades\Theme;
+use BookStack\Theming\ThemeEvents;
 use Exception;
 use Illuminate\Support\Str;
 use OneLogin\Saml2\Auth;
@@ -375,6 +377,7 @@ class Saml2Service extends ExternalAuthService
 
         auth()->login($user);
         Activity::add(ActivityType::AUTH_LOGIN, "saml2; {$user->logDescriptor()}");
+        Theme::dispatch(ThemeEvents::AUTH_LOGIN, 'saml2', $user);
         return $user;
     }
 }
index f7a166d0e6cb4027bcd8f7487dd53b37732a08c4..7c8b66ea57ab6ad84b6a7aa839b6d223ee98a039 100644 (file)
@@ -7,6 +7,8 @@ use BookStack\Exceptions\SocialDriverNotConfigured;
 use BookStack\Exceptions\SocialSignInAccountNotUsed;
 use BookStack\Exceptions\UserRegistrationException;
 use BookStack\Facades\Activity;
+use BookStack\Facades\Theme;
+use BookStack\Theming\ThemeEvents;
 use Illuminate\Support\Facades\Event;
 use Illuminate\Support\Str;
 use Laravel\Socialite\Contracts\Factory as Socialite;
@@ -58,7 +60,7 @@ class SocialAuthService
     {
         // Check social account has not already been used
         if (SocialAccount::query()->where('driver_id', '=', $socialUser->getId())->exists()) {
-            throw new UserRegistrationException(trans('errors.social_account_in_use', ['socialAccount'=>$socialDriver]), '/login');
+            throw new UserRegistrationException(trans('errors.social_account_in_use', ['socialAccount' => $socialDriver]), '/login');
         }
 
         if (User::query()->where('email', '=', $socialUser->getEmail())->exists()) {
@@ -98,6 +100,7 @@ class SocialAuthService
         if (!$isLoggedIn && $socialAccount !== null) {
             auth()->login($socialAccount->user);
             Activity::add(ActivityType::AUTH_LOGIN, $socialAccount);
+            Theme::dispatch(ThemeEvents::AUTH_LOGIN, $socialDriver, $socialAccount->user);
             return redirect()->intended('/');
         }
 
@@ -127,7 +130,7 @@ class SocialAuthService
         if (setting('registration-enabled') && config('auth.method') !== 'ldap' && config('auth.method') !== 'saml2') {
             $message .= trans('errors.social_account_register_instructions', ['socialAccount' => $titleCaseDriver]);
         }
-        
+
         throw new SocialSignInAccountNotUsed($message, '/login');
     }
 
@@ -207,9 +210,9 @@ class SocialAuthService
     public function newSocialAccount(string $socialDriver, SocialUser $socialUser): SocialAccount
     {
         return new SocialAccount([
-            'driver'    => $socialDriver,
+            'driver' => $socialDriver,
             'driver_id' => $socialUser->getId(),
-            'avatar'    => $socialUser->getAvatar()
+            'avatar' => $socialUser->getAvatar()
         ]);
     }
 
index bffeb5f61b2f2f7528b87e6ad506f4b6dded53d2..6e6a0e779d0871e49e9863ffd76a5f8373288395 100644 (file)
@@ -2,12 +2,15 @@
 
 namespace BookStack\Http\Controllers\Auth;
 
+use BookStack\Actions\ActivityType;
 use BookStack\Auth\Access\EmailConfirmationService;
 use BookStack\Auth\UserRepo;
 use BookStack\Exceptions\ConfirmationEmailException;
 use BookStack\Exceptions\UserTokenExpiredException;
 use BookStack\Exceptions\UserTokenNotFoundException;
+use BookStack\Facades\Theme;
 use BookStack\Http\Controllers\Controller;
+use BookStack\Theming\ThemeEvents;
 use Exception;
 use Illuminate\Http\RedirectResponse;
 use Illuminate\Http\Request;
@@ -80,6 +83,8 @@ class ConfirmEmailController extends Controller
         $user->save();
 
         auth()->login($user);
+        Theme::dispatch(ThemeEvents::AUTH_LOGIN, auth()->getDefaultDriver(), $user);
+        $this->logActivity(ActivityType::AUTH_LOGIN, $user);
         $this->showSuccessNotification(trans('auth.email_confirm_success'));
         $this->emailConfirmationService->deleteByUser($user);
 
index d5685644ea5c32f80076feb3a5529bc27c563fbc..01255f466886005e26c155b7217133bbc6f76825 100644 (file)
@@ -7,7 +7,9 @@ use BookStack\Actions\ActivityType;
 use BookStack\Auth\Access\SocialAuthService;
 use BookStack\Exceptions\LoginAttemptEmailNeededException;
 use BookStack\Exceptions\LoginAttemptException;
+use BookStack\Facades\Theme;
 use BookStack\Http\Controllers\Controller;
+use BookStack\Theming\ThemeEvents;
 use Illuminate\Foundation\Auth\AuthenticatesUsers;
 use Illuminate\Http\Request;
 
@@ -150,6 +152,7 @@ class LoginController extends Controller
             }
         }
 
+        Theme::dispatch(ThemeEvents::AUTH_LOGIN, auth()->getDefaultDriver(), $user);
         $this->logActivity(ActivityType::AUTH_LOGIN, $user);
         return redirect()->intended($this->redirectPath());
     }
index cbec1f03f6e3b0b58704b17de79e21f8bf975a8c..7d7d8732b5f1e37d1177b230f8229b9d65b9c07f 100644 (file)
@@ -2,11 +2,14 @@
 
 namespace BookStack\Http\Controllers\Auth;
 
+use BookStack\Actions\ActivityType;
 use BookStack\Auth\Access\RegistrationService;
 use BookStack\Auth\Access\SocialAuthService;
 use BookStack\Auth\User;
 use BookStack\Exceptions\UserRegistrationException;
+use BookStack\Facades\Theme;
 use BookStack\Http\Controllers\Controller;
+use BookStack\Theming\ThemeEvents;
 use Illuminate\Foundation\Auth\RegistersUsers;
 use Illuminate\Http\Request;
 use Illuminate\Support\Facades\Hash;
@@ -93,6 +96,8 @@ class RegisterController extends Controller
         try {
             $user = $this->registrationService->registerUser($userData);
             auth()->login($user);
+            Theme::dispatch(ThemeEvents::AUTH_LOGIN, auth()->getDefaultDriver(), $user);
+            $this->logActivity(ActivityType::AUTH_LOGIN, $user);
         } catch (UserRegistrationException $exception) {
             if ($exception->getMessage()) {
                 $this->showErrorNotification($exception->getMessage());
index 428194e075085454273d252498c898e6b9a032f9..447f0afc9358f85eb8e7975ea08930878c332c1a 100644 (file)
@@ -2,13 +2,16 @@
 
 namespace BookStack\Http\Controllers\Auth;
 
+use BookStack\Actions\ActivityType;
 use BookStack\Auth\Access\RegistrationService;
 use BookStack\Auth\Access\SocialAuthService;
 use BookStack\Exceptions\SocialDriverNotConfigured;
 use BookStack\Exceptions\SocialSignInAccountNotUsed;
 use BookStack\Exceptions\SocialSignInException;
 use BookStack\Exceptions\UserRegistrationException;
+use BookStack\Facades\Theme;
 use BookStack\Http\Controllers\Controller;
+use BookStack\Theming\ThemeEvents;
 use Illuminate\Http\Request;
 use Illuminate\Support\Str;
 use Laravel\Socialite\Contracts\User as SocialUser;
@@ -127,6 +130,8 @@ class SocialController extends Controller
 
         $user = $this->registrationService->registerUser($userData, $socialAccount, $emailVerified);
         auth()->login($user);
+        Theme::dispatch(ThemeEvents::AUTH_LOGIN, $socialDriver, $user);
+        $this->logActivity(ActivityType::AUTH_LOGIN, $user);
 
         $this->showSuccessNotification(trans('auth.register_success'));
         return redirect('/');
index 926458fa613ddc1073305ea5405750c7ce01e085..ab745224836d4e82477e0513999d049c07a4528f 100644 (file)
@@ -2,11 +2,14 @@
 
 namespace BookStack\Http\Controllers\Auth;
 
+use BookStack\Actions\ActivityType;
 use BookStack\Auth\Access\UserInviteService;
 use BookStack\Auth\UserRepo;
 use BookStack\Exceptions\UserTokenExpiredException;
 use BookStack\Exceptions\UserTokenNotFoundException;
+use BookStack\Facades\Theme;
 use BookStack\Http\Controllers\Controller;
+use BookStack\Theming\ThemeEvents;
 use Exception;
 use Illuminate\Http\RedirectResponse;
 use Illuminate\Http\Request;
@@ -68,6 +71,8 @@ class UserInviteController extends Controller
         $user->save();
 
         auth()->login($user);
+        Theme::dispatch(ThemeEvents::AUTH_LOGIN, auth()->getDefaultDriver(), $user);
+        $this->logActivity(ActivityType::AUTH_LOGIN, $user);
         $this->showSuccessNotification(trans('auth.user_invite_success', ['appName' => setting('app-name')]));
         $this->inviteService->deleteByUser($user);
 
index a81179ed7cd86e5341aecbec1d72b3926b2b1b63..56e1fba1ccd70f4a3342047f6d20ec13d6f4822b 100644 (file)
@@ -41,6 +41,26 @@ class ThemeEvents
      */
     const WEB_MIDDLEWARE_AFTER = 'web_middleware_after';
 
+    /**
+     * Auth login event.
+     * Runs right after a user is logged-in to the application by any authentication
+     * system as a standard app user. This includes a user becoming logged in
+     * after registration. This is not emitted upon API usage.
+     * @param string $authSystem
+     * @param \BookStack\Auth\User $user
+     */
+    const AUTH_LOGIN = 'auth_login';
+
+    /**
+     * Auth register event.
+     * Runs right after a user is newly registered to the application by any authentication
+     * system as a standard app user. This includes auto-registration systems used
+     * by LDAP, SAML and social systems. It only includes self-registrations.
+     * @param string $authSystem
+     * @param \BookStack\Auth\User $user
+     */
+    const AUTH_REGISTER = 'auth_register';
+
     /**
      * Commonmark environment configure.
      * Provides the commonmark library environment for customization
index d448b567e5ef1462bf168500bc2dc6b8ed1df2f2..4369d8b7abca6faa84780f73c13bdd4176176aac 100644 (file)
@@ -17,8 +17,7 @@ class SocialAuthTest extends TestCase
         $this->setSettings(['registration-enabled' => 'true']);
         config(['GOOGLE_APP_ID' => 'abc123', 'GOOGLE_APP_SECRET' => '123abc', 'APP_URL' => 'http://localhost']);
 
-        $mockSocialite = Mockery::mock(Factory::class);
-        $this->app[Factory::class] = $mockSocialite;
+        $mockSocialite = $this->mock(Factory::class);
         $mockSocialDriver = Mockery::mock(Provider::class);
         $mockSocialUser = Mockery::mock(\Laravel\Socialite\Contracts\User::class);
 
@@ -46,8 +45,7 @@ class SocialAuthTest extends TestCase
             'APP_URL' => 'http://localhost'
         ]);
 
-        $mockSocialite = Mockery::mock(Factory::class);
-        $this->app[Factory::class] = $mockSocialite;
+        $mockSocialite = $this->mock(Factory::class);
         $mockSocialDriver = Mockery::mock(Provider::class);
         $mockSocialUser = Mockery::mock(\Laravel\Socialite\Contracts\User::class);
 
@@ -93,8 +91,7 @@ class SocialAuthTest extends TestCase
         ]);
 
         $user = factory(User::class)->make();
-        $mockSocialite = Mockery::mock(Factory::class);
-        $this->app[Factory::class] = $mockSocialite;
+        $mockSocialite = $this->mock(Factory::class);
         $mockSocialDriver = Mockery::mock(Provider::class);
         $mockSocialUser = Mockery::mock(\Laravel\Socialite\Contracts\User::class);
 
@@ -132,8 +129,7 @@ class SocialAuthTest extends TestCase
         ]);
 
         $user = factory(User::class)->make();
-        $mockSocialite = Mockery::mock(Factory::class);
-        $this->app[Factory::class] = $mockSocialite;
+        $mockSocialite = $this->mock(Factory::class);
         $mockSocialDriver = Mockery::mock(Provider::class);
         $mockSocialUser = Mockery::mock(\Laravel\Socialite\Contracts\User::class);
 
@@ -169,8 +165,7 @@ class SocialAuthTest extends TestCase
         $this->setSettings(['registration-enabled' => 'true']);
         config(['GITHUB_APP_ID' => 'abc123', 'GITHUB_APP_SECRET' => '123abc', 'APP_URL' => 'http://localhost']);
 
-        $mockSocialite = Mockery::mock(Factory::class);
-        $this->app[Factory::class] = $mockSocialite;
+        $mockSocialite = $this->mock(Factory::class);
         $mockSocialDriver = Mockery::mock(Provider::class);
         $mockSocialUser = Mockery::mock(\Laravel\Socialite\Contracts\User::class);
 
index 198c2b0aac3112cc855ae103cd09802a6bef3277..7a0cd49cb54696353841012b605b3404565298fb 100644 (file)
@@ -1,5 +1,7 @@
 <?php namespace Tests;
 
+use BookStack\Auth\Access\SocialAuthService;
+use BookStack\Auth\User;
 use BookStack\Entities\Models\Page;
 use BookStack\Entities\Tools\PageContent;
 use BookStack\Facades\Theme;
@@ -122,6 +124,38 @@ class ThemeTest extends TestCase
         $resp->assertStatus(443);
     }
 
+    public function test_event_auth_login_standard()
+    {
+        $args = [];
+        $callback = function (...$eventArgs) use (&$args) {
+            $args = $eventArgs;
+        };
+
+        Theme::listen(ThemeEvents::AUTH_LOGIN, $callback);
+        $this->post('/login', ['email' => '[email protected]', 'password' => 'password']);
+
+        $this->assertCount(2, $args);
+        $this->assertEquals('standard', $args[0]);
+        $this->assertInstanceOf(User::class, $args[1]);
+    }
+
+    public function test_event_auth_register_standard()
+    {
+        $args = [];
+        $callback = function (...$eventArgs) use (&$args) {
+            $args = $eventArgs;
+        };
+        Theme::listen(ThemeEvents::AUTH_REGISTER, $callback);
+        $this->setSettings(['registration-enabled' => 'true']);
+
+        $user = factory(User::class)->make();
+        $this->post('/register', ['email' => $user->email, 'name' => $user->name,  'password' => 'password']);
+
+        $this->assertCount(2, $args);
+        $this->assertEquals('standard', $args[0]);
+        $this->assertInstanceOf(User::class, $args[1]);
+    }
+
     public function test_add_social_driver()
     {
         Theme::addSocialDriver('catnet', [