1 <?php namespace BookStack\Auth\Access;
3 use BookStack\Auth\User;
4 use BookStack\Exceptions\UserTokenExpiredException;
5 use BookStack\Exceptions\UserTokenNotFoundException;
7 use Illuminate\Database\Connection as Database;
8 use Illuminate\Support\Str;
11 class UserTokenService
15 * Name of table where user tokens are stored.
18 protected $tokenTable = 'user_tokens';
21 * Token expiry time in hours.
24 protected $expiryTime = 24;
29 * UserTokenService constructor.
32 public function __construct(Database $db)
38 * Delete all email confirmations that belong to a user.
42 public function deleteByUser(User $user)
44 return $this->db->table($this->tokenTable)
45 ->where('user_id', '=', $user->id)
50 * Get the user id from a token, while check the token exists and has not expired.
51 * @param string $token
53 * @throws UserTokenNotFoundException
54 * @throws UserTokenExpiredException
56 public function checkTokenAndGetUserId(string $token) : int
58 $entry = $this->getEntryByToken($token);
60 if (is_null($entry)) {
61 throw new UserTokenNotFoundException('Token "' . $token . '" not found');
64 if ($this->entryExpired($entry)) {
65 throw new UserTokenExpiredException("Token of id {$entry->id} has expired.", $entry->user_id);
68 return $entry->user_id;
72 * Creates a unique token within the email confirmation database.
75 protected function generateToken() : string
77 $token = Str::random(24);
78 while ($this->tokenExists($token)) {
79 $token = Str::random(25);
85 * Generate and store a token for the given user.
89 protected function createTokenForUser(User $user) : string
91 $token = $this->generateToken();
92 $this->db->table($this->tokenTable)->insert([
93 'user_id' => $user->id,
95 'created_at' => Carbon::now(),
96 'updated_at' => Carbon::now()
102 * Check if the given token exists.
103 * @param string $token
106 protected function tokenExists(string $token) : bool
108 return $this->db->table($this->tokenTable)
109 ->where('token', '=', $token)->exists();
113 * Get a token entry for the given token.
114 * @param string $token
115 * @return object|null
117 protected function getEntryByToken(string $token)
119 return $this->db->table($this->tokenTable)
120 ->where('token', '=', $token)
125 * Check if the given token entry has expired.
126 * @param stdClass $tokenEntry
129 protected function entryExpired(stdClass $tokenEntry) : bool
131 return Carbon::now()->subHours($this->expiryTime)
132 ->gt(new Carbon($tokenEntry->created_at));