]> BookStack Code Mirror - bookstack/blobdiff - app/Auth/Access/Guards/LdapSessionGuard.php
Update Localization.php in Middleware with "no" tag for estimate.
[bookstack] / app / Auth / Access / Guards / LdapSessionGuard.php
index 6c416bf301621c31a8c887883b7470b2b0553557..652141c0ce280963abc337f20cd62e19d79e6f40 100644 (file)
@@ -3,13 +3,17 @@
 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
 {
@@ -23,11 +27,11 @@ class LdapSessionGuard extends ExternalBaseSessionGuard
         UserProvider $provider,
         Session $session,
         LdapService $ldapService,
-        UserRepo $userRepo
+        RegistrationService $registrationService
     )
     {
         $this->ldapService = $ldapService;
-        parent::__construct($name, $provider, $session, $userRepo);
+        parent::__construct($name, $provider, $session, $registrationService);
     }
 
     /**
@@ -40,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']);
     }
 
     /**
@@ -53,7 +60,6 @@ class LdapSessionGuard extends ExternalBaseSessionGuard
      * @param array $credentials
      * @param bool $remember
      * @return bool
-     * @throws LoginAttemptEmailNeededException
      * @throws LoginAttemptException
      * @throws LdapException
      */
@@ -61,21 +67,26 @@ class LdapSessionGuard extends ExternalBaseSessionGuard
     {
         $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'])) {
+        $user = null;
+        if (isset($userDetails['uid'])) {
+            $this->lastAttempted = $user = $this->provider->retrieveByCredentials([
+                'external_auth_id' => $userDetails['uid']
+            ]);
+        }
+
+        if (!$this->ldapService->validateUserCredentials($userDetails, $credentials['password'])) {
             return false;
         }
 
         if (is_null($user)) {
-            $user = $this->freshUserInstanceFromLdapUserDetails($userDetails);
+            try {
+                $user = $this->createNewFromLdapAndCreds($userDetails, $credentials);
+            } catch (UserRegistrationException $exception) {
+                throw new LoginAttemptException($exception->message);
+            }
         }
 
-        $this->checkForUserEmail($user, $credentials['email'] ?? '');
-        $this->saveIfNew($user);
-
         // Sync LDAP groups if required
         if ($this->ldapService->shouldSyncGroups()) {
             $this->ldapService->syncGroups($user, $username);
@@ -86,58 +97,27 @@ class LdapSessionGuard extends ExternalBaseSessionGuard
     }
 
     /**
-     * Save the give user if they don't yet existing in the system.
+     * Create a new user from the given ldap credentials and login credentials
+     * @throws LoginAttemptEmailNeededException
      * @throws LoginAttemptException
+     * @throws UserRegistrationException
      */
-    protected function saveIfNew(User $user)
+    protected function createNewFromLdapAndCreds(array $ldapUserDetails, array $credentials): User
     {
-        if ($user->exists) {
-            return;
-        }
-
-        // 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);
-    }
+        $email = trim($ldapUserDetails['email'] ?: ($credentials['email'] ?? ''));
 
-    /**
-     * Ensure the given user has an email.
-     * Takes the provided email in the request if a value is provided
-     * and the user does not have an existing email.
-     * @throws LoginAttemptEmailNeededException
-     */
-    protected function checkForUserEmail(User $user, string $providedEmail)
-    {
-        // Request email if missing from user and missing from request
-        if (is_null($user->email) && !$providedEmail) {
+        if (empty($email)) {
             throw new LoginAttemptEmailNeededException();
         }
 
-        // Add email to model if non-existing and email provided in request
-        if (!$user->exists && is_null($user->email) && $providedEmail) {
-            $user->email = $providedEmail;
-        }
-    }
-
-    /**
-     * Create a fresh user instance from details provided by a LDAP lookup.
-     */
-    protected function freshUserInstanceFromLdapUserDetails(array $ldapUserDetails): User
-    {
-        $user = new User();
-
-        $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);
     }
 
 }