]> BookStack Code Mirror - bookstack/blob - app/Auth/Access/Guards/LdapSessionGuard.php
Started work on details/summary blocks
[bookstack] / app / Auth / Access / Guards / LdapSessionGuard.php
1 <?php
2
3 namespace BookStack\Auth\Access\Guards;
4
5 use BookStack\Auth\Access\LdapService;
6 use BookStack\Auth\Access\RegistrationService;
7 use BookStack\Auth\User;
8 use BookStack\Exceptions\LdapException;
9 use BookStack\Exceptions\LoginAttemptEmailNeededException;
10 use BookStack\Exceptions\LoginAttemptException;
11 use BookStack\Exceptions\UserRegistrationException;
12 use Illuminate\Contracts\Auth\UserProvider;
13 use Illuminate\Contracts\Session\Session;
14 use Illuminate\Support\Str;
15
16 class LdapSessionGuard extends ExternalBaseSessionGuard
17 {
18     protected $ldapService;
19
20     /**
21      * LdapSessionGuard constructor.
22      */
23     public function __construct(
24         $name,
25         UserProvider $provider,
26         Session $session,
27         LdapService $ldapService,
28         RegistrationService $registrationService
29     ) {
30         $this->ldapService = $ldapService;
31         parent::__construct($name, $provider, $session, $registrationService);
32     }
33
34     /**
35      * Validate a user's credentials.
36      *
37      * @param array $credentials
38      *
39      * @throws LdapException
40      *
41      * @return bool
42      */
43     public function validate(array $credentials = [])
44     {
45         $userDetails = $this->ldapService->getUserDetails($credentials['username']);
46
47         if (isset($userDetails['uid'])) {
48             $this->lastAttempted = $this->provider->retrieveByCredentials([
49                 'external_auth_id' => $userDetails['uid'],
50             ]);
51         }
52
53         return $this->ldapService->validateUserCredentials($userDetails, $credentials['password']);
54     }
55
56     /**
57      * Attempt to authenticate a user using the given credentials.
58      *
59      * @param array $credentials
60      * @param bool  $remember
61      *
62      * @throws LoginAttemptException
63      * @throws LdapException
64      *
65      * @return bool
66      */
67     public function attempt(array $credentials = [], $remember = false)
68     {
69         $username = $credentials['username'];
70         $userDetails = $this->ldapService->getUserDetails($username);
71
72         $user = null;
73         if (isset($userDetails['uid'])) {
74             $this->lastAttempted = $user = $this->provider->retrieveByCredentials([
75                 'external_auth_id' => $userDetails['uid'],
76             ]);
77         }
78
79         if (!$this->ldapService->validateUserCredentials($userDetails, $credentials['password'])) {
80             return false;
81         }
82
83         if (is_null($user)) {
84             try {
85                 $user = $this->createNewFromLdapAndCreds($userDetails, $credentials);
86             } catch (UserRegistrationException $exception) {
87                 throw new LoginAttemptException($exception->message);
88             }
89         }
90
91         // Sync LDAP groups if required
92         if ($this->ldapService->shouldSyncGroups()) {
93             $this->ldapService->syncGroups($user, $username);
94         }
95
96         // Attach avatar if non-existent
97         if (!$user->avatar()->exists()) {
98             $this->ldapService->saveAndAttachAvatar($user, $userDetails);
99         }
100
101         $this->login($user, $remember);
102
103         return true;
104     }
105
106     /**
107      * Create a new user from the given ldap credentials and login credentials.
108      *
109      * @throws LoginAttemptEmailNeededException
110      * @throws LoginAttemptException
111      * @throws UserRegistrationException
112      */
113     protected function createNewFromLdapAndCreds(array $ldapUserDetails, array $credentials): User
114     {
115         $email = trim($ldapUserDetails['email'] ?: ($credentials['email'] ?? ''));
116
117         if (empty($email)) {
118             throw new LoginAttemptEmailNeededException();
119         }
120
121         $details = [
122             'name'             => $ldapUserDetails['name'],
123             'email'            => $ldapUserDetails['email'] ?: $credentials['email'],
124             'external_auth_id' => $ldapUserDetails['uid'],
125             'password'         => Str::random(32),
126         ];
127
128         $user = $this->registrationService->registerUser($details, null, false);
129         $this->ldapService->saveAndAttachAvatar($user, $ldapUserDetails);
130
131         return $user;
132     }
133 }