]> BookStack Code Mirror - bookstack/blobdiff - app/Auth/Access/Guards/LdapSessionGuard.php
Add footer element, styles, and associated settings
[bookstack] / app / Auth / Access / Guards / LdapSessionGuard.php
index ad173cf73fef2ec4787c7be5ba500705d32e35a2..84f54ad292c9191479519840dc79b736db40bcb3 100644 (file)
@@ -3,19 +3,22 @@
 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
 {
 
     protected $ldapService;
-    protected $userRepo;
 
     /**
      * LdapSessionGuard constructor.
@@ -24,12 +27,11 @@ class LdapSessionGuard extends ExternalBaseSessionGuard
         UserProvider $provider,
         Session $session,
         LdapService $ldapService,
-        UserRepo $userRepo
+        RegistrationService $registrationService
     )
     {
         $this->ldapService = $ldapService;
-        $this->userRepo = $userRepo;
-        parent::__construct($name, $provider, $session);
+        parent::__construct($name, $provider, $session, $registrationService);
     }
 
     /**
@@ -42,11 +44,14 @@ class LdapSessionGuard extends ExternalBaseSessionGuard
     public function validate(array $credentials = [])
     {
         $userDetails = $this->ldapService->getUserDetails($credentials['username']);
-        $this->lastAttempted = $this->provider->retrieveByCredentials([
-            'external_auth_id' => $userDetails['uid']
-        ]);
 
-        return $this->ldapService->validateUserCredentials($userDetails, $credentials['username'], $credentials['password']);
+        if (isset($userDetails['uid'])) {
+            $this->lastAttempted = $this->provider->retrieveByCredentials([
+                'external_auth_id' => $userDetails['uid']
+            ]);
+        }
+
+        return $this->ldapService->validateUserCredentials($userDetails, $credentials['password']);
     }
 
     /**
@@ -58,45 +63,26 @@ class LdapSessionGuard extends ExternalBaseSessionGuard
      * @throws LoginAttemptEmailNeededException
      * @throws LoginAttemptException
      * @throws LdapException
+     * @throws UserRegistrationException
      */
     public function attempt(array $credentials = [], $remember = false)
     {
         $username = $credentials['username'];
         $userDetails = $this->ldapService->getUserDetails($username);
-        $this->lastAttempted = $user = $this->provider->retrieveByCredentials([
-            'external_auth_id' => $userDetails['uid']
-        ]);
-
-        if (!$this->ldapService->validateUserCredentials($userDetails, $username, $credentials['password'])) {
-            return false;
-        }
-
-        if (is_null($user)) {
-            $user = $this->freshUserInstanceFromLdapUserDetails($userDetails);
-        }
-
-        $providedEmail = ($credentials['email'] ?? false);
 
-        // Request email if missing from LDAP and model and missing from request
-        if (is_null($user->email) && !$providedEmail) {
-            throw new LoginAttemptEmailNeededException();
+        $user = null;
+        if (isset($userDetails['uid'])) {
+            $this->lastAttempted = $user = $this->provider->retrieveByCredentials([
+                'external_auth_id' => $userDetails['uid']
+            ]);
         }
 
-        // Add email to model if non-existing and email provided in request
-        if (!$user->exists && $user->email === null && $providedEmail) {
-            $user->email = $providedEmail;
+        if (!$this->ldapService->validateUserCredentials($userDetails, $credentials['password'])) {
+            return false;
         }
 
-        if (!$user->exists) {
-            // Check for existing users with same email
-            $alreadyUser = $user->newQuery()->where('email', '=', $user->email)->count() > 0;
-            if ($alreadyUser) {
-                throw new LoginAttemptException(trans('errors.error_user_exists_different_creds', ['email' => $user->email]));
-            }
-
-            $user->save();
-            $this->userRepo->attachDefaultRole($user);
-            $this->userRepo->downloadAndAssignUserAvatar($user);
+        if (is_null($user)) {
+            $user = $this->createNewFromLdapAndCreds($userDetails, $credentials);
         }
 
         // Sync LDAP groups if required
@@ -109,18 +95,27 @@ class LdapSessionGuard extends ExternalBaseSessionGuard
     }
 
     /**
-     * Create a fresh user instance from details provided by a LDAP lookup.
+     * Create a new user from the given ldap credentials and login credentials
+     * @throws LoginAttemptEmailNeededException
+     * @throws LoginAttemptException
+     * @throws UserRegistrationException
      */
-    protected function freshUserInstanceFromLdapUserDetails(array $ldapUserDetails): User
+    protected function createNewFromLdapAndCreds(array $ldapUserDetails, array $credentials): User
     {
-        $user = new User();
+        $email = trim($ldapUserDetails['email'] ?: ($credentials['email'] ?? ''));
+
+        if (empty($email)) {
+            throw new LoginAttemptEmailNeededException();
+        }
 
-        $user->name = $ldapUserDetails['name'];
-        $user->external_auth_id = $ldapUserDetails['uid'];
-        $user->email = $ldapUserDetails['email'];
-        $user->email_confirmed = false;
+        $details = [
+            'name' => $ldapUserDetails['name'],
+            'email' => $ldapUserDetails['email'] ?: $credentials['email'],
+            'external_auth_id' => $ldapUserDetails['uid'],
+            'password' => Str::random(32),
+        ];
 
-        return $user;
+        return $this->registrationService->registerUser($details, null, false);
     }
 
 }