3 namespace BookStack\Access\Guards;
5 use BookStack\Access\RegistrationService;
6 use Illuminate\Auth\GuardHelpers;
7 use Illuminate\Contracts\Auth\Authenticatable;
8 use Illuminate\Contracts\Auth\StatefulGuard;
9 use Illuminate\Contracts\Auth\UserProvider;
10 use Illuminate\Contracts\Session\Session;
13 * Class BaseSessionGuard
14 * A base implementation of a session guard. Is a copy of the default Laravel
15 * guard with 'remember' functionality removed. Basic auth and event emission
16 * has also been removed to keep this simple. Designed to be extended by external
19 class ExternalBaseSessionGuard implements StatefulGuard
24 * The name of the Guard. Typically "session".
26 * Corresponds to guard name in authentication configuration.
28 protected readonly string $name;
31 * The user we last attempted to retrieve.
33 protected Authenticatable|null $lastAttempted;
36 * The session used by the guard.
38 protected Session $session;
41 * Indicates if the logout method has been called.
43 protected bool $loggedOut = false;
46 * Service to handle common registration actions.
48 protected RegistrationService $registrationService;
51 * Create a new authentication guard.
53 public function __construct(string $name, UserProvider $provider, Session $session, RegistrationService $registrationService)
56 $this->session = $session;
57 $this->provider = $provider;
58 $this->registrationService = $registrationService;
62 * Get the currently authenticated user.
64 public function user(): Authenticatable|null
66 if ($this->loggedOut) {
70 // If we've already retrieved the user for the current request we can just
71 // return it back immediately. We do not want to fetch the user data on
72 // every call to this method because that would be tremendously slow.
73 if (!is_null($this->user)) {
77 $id = $this->session->get($this->getName());
79 // First we will try to load the user using the
80 // identifier in the session if one exists.
82 $this->user = $this->provider->retrieveById($id);
89 * Get the ID for the currently authenticated user.
91 public function id(): int|null
93 if ($this->loggedOut) {
98 ? $this->user()->getAuthIdentifier()
99 : $this->session->get($this->getName());
103 * Log a user into the application without sessions or cookies.
105 public function once(array $credentials = []): bool
107 if ($this->validate($credentials)) {
108 $this->setUser($this->lastAttempted);
117 * Log the given user ID into the application without sessions or cookies.
119 public function onceUsingId($id): Authenticatable|false
121 if (!is_null($user = $this->provider->retrieveById($id))) {
122 $this->setUser($user);
131 * Validate a user's credentials.
133 public function validate(array $credentials = []): bool
139 * Attempt to authenticate a user using the given credentials.
140 * @param bool $remember
142 public function attempt(array $credentials = [], $remember = false): bool
148 * Log the given user ID into the application.
149 * @param bool $remember
151 public function loginUsingId(mixed $id, $remember = false): Authenticatable|false
153 // Always return false as to disable this method,
154 // Logins should route through LoginService.
159 * Log a user into the application.
161 * @param bool $remember
163 public function login(Authenticatable $user, $remember = false): void
165 $this->updateSession($user->getAuthIdentifier());
167 $this->setUser($user);
171 * Update the session with the given ID.
173 protected function updateSession(string|int $id): void
175 $this->session->put($this->getName(), $id);
177 $this->session->migrate(true);
181 * Log the user out of the application.
183 public function logout(): void
185 $this->clearUserDataFromStorage();
187 // Now we will clear the users out of memory so they are no longer available
188 // as the user is no longer considered as being signed into this
189 // application and should not be available here.
192 $this->loggedOut = true;
196 * Remove the user data from the session and cookies.
198 protected function clearUserDataFromStorage(): void
200 $this->session->remove($this->getName());
204 * Get the last user we attempted to authenticate.
206 public function getLastAttempted(): Authenticatable
208 return $this->lastAttempted;
212 * Get a unique identifier for the auth session value.
214 public function getName(): string
216 return 'login_' . $this->name . '_' . sha1(static::class);
220 * Determine if the user was authenticated via "remember me" cookie.
222 public function viaRemember(): bool
228 * Return the currently cached user.
230 public function getUser(): Authenticatable|null
236 * Set the current user.
238 public function setUser(Authenticatable $user): self
242 $this->loggedOut = false;