2022-03-19 00:14:20 +01:00
|
|
|
<?php
|
|
|
|
|
2022-03-24 14:58:30 +01:00
|
|
|
// Largely inspired by Firefly III remote user implementation (https://github.com/firefly-iii)
|
2022-03-19 00:14:20 +01:00
|
|
|
// see https://github.com/firefly-iii/firefly-iii/blob/main/app/Support/Authentication/RemoteUserProvider.php
|
|
|
|
|
|
|
|
namespace App\Extensions;
|
|
|
|
|
|
|
|
use App\Models\User;
|
2022-11-22 15:15:52 +01:00
|
|
|
use Exception;
|
2022-03-19 00:14:20 +01:00
|
|
|
use Illuminate\Contracts\Auth\Authenticatable;
|
|
|
|
use Illuminate\Contracts\Auth\UserProvider;
|
2023-03-12 17:47:40 +01:00
|
|
|
use Illuminate\Support\Facades\Log;
|
|
|
|
use Illuminate\Support\Facades\Validator;
|
|
|
|
use Illuminate\Support\Str;
|
|
|
|
use Illuminate\Validation\ValidationException;
|
2022-03-19 00:14:20 +01:00
|
|
|
|
|
|
|
class RemoteUserProvider implements UserProvider
|
|
|
|
{
|
2024-04-24 14:06:15 +02:00
|
|
|
const FAKE_REMOTE_DOMAIN = '@remote';
|
2024-04-26 08:01:20 +02:00
|
|
|
|
2022-09-07 17:58:34 +02:00
|
|
|
/**
|
|
|
|
* The currently authenticated user.
|
|
|
|
*
|
|
|
|
* @var \App\Models\User|null
|
|
|
|
*/
|
|
|
|
protected $user;
|
|
|
|
|
2022-03-19 00:14:20 +01:00
|
|
|
/**
|
2022-11-22 15:15:52 +01:00
|
|
|
* {@inheritDoc}
|
2022-03-19 00:14:20 +01:00
|
|
|
*/
|
2022-03-24 14:58:30 +01:00
|
|
|
public function retrieveById($identifier)
|
2022-03-19 00:14:20 +01:00
|
|
|
{
|
2023-03-12 17:47:40 +01:00
|
|
|
// We don't know the id length so we trim it to prevent to long strings in DB
|
2023-03-13 14:53:42 +01:00
|
|
|
$name = substr($identifier['id'], 0, 191);
|
2023-03-12 17:47:40 +01:00
|
|
|
$email = null;
|
2022-09-07 17:58:34 +02:00
|
|
|
|
2023-03-12 17:47:40 +01:00
|
|
|
$user = User::where('name', $name)->first();
|
|
|
|
|
|
|
|
// We use the passed email only if it is valid and no account is using it.
|
|
|
|
if ($identifier['email']) {
|
|
|
|
try {
|
|
|
|
$validated = Validator::validate([
|
|
|
|
'email' => $identifier['email'],
|
|
|
|
], [
|
|
|
|
'email' => 'email',
|
|
|
|
]);
|
|
|
|
|
|
|
|
if (User::where('id', '<>', $user->id ?? 0)->where('email', $identifier['email'])->count() == 0) {
|
2023-03-13 14:53:42 +01:00
|
|
|
$email = strtolower($identifier['email']);
|
2023-03-12 17:47:40 +01:00
|
|
|
}
|
|
|
|
} catch (ValidationException $e) {
|
|
|
|
// do nothing
|
|
|
|
}
|
2022-09-07 17:58:34 +02:00
|
|
|
}
|
2023-03-12 17:47:40 +01:00
|
|
|
|
|
|
|
if (is_null($user)) {
|
2023-03-13 14:53:42 +01:00
|
|
|
$email = $email ?? $this->fakeRemoteEmail($identifier['id']);
|
|
|
|
|
2023-03-12 17:47:40 +01:00
|
|
|
$user = User::create([
|
|
|
|
'name' => $name,
|
|
|
|
'email' => strtolower($email),
|
|
|
|
'password' => bcrypt(Str::random(64)),
|
|
|
|
]);
|
|
|
|
|
|
|
|
Log::info(sprintf('Remote user %s created with email address %s', var_export($user->name, true), var_export($user->email, true)));
|
|
|
|
|
|
|
|
if (User::count() === 1) {
|
2024-01-26 18:14:02 +01:00
|
|
|
$user->promoteToAdministrator();
|
2023-03-12 17:47:40 +01:00
|
|
|
$user->save();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Here we keep the account's email sync-ed
|
2023-03-13 14:53:42 +01:00
|
|
|
if ($email && $user->email != $email) {
|
2023-03-12 17:47:40 +01:00
|
|
|
$user->email = $email;
|
|
|
|
$user->save();
|
|
|
|
}
|
2022-09-07 17:58:34 +02:00
|
|
|
}
|
2022-03-19 00:14:20 +01:00
|
|
|
|
|
|
|
return $user;
|
|
|
|
}
|
|
|
|
|
2023-03-12 17:47:40 +01:00
|
|
|
/**
|
|
|
|
* Set a fake email address
|
|
|
|
*
|
2024-04-20 19:03:44 +02:00
|
|
|
* @param $id mixed
|
2023-03-12 17:47:40 +01:00
|
|
|
* @return string
|
|
|
|
*/
|
2023-03-13 14:53:42 +01:00
|
|
|
protected function fakeRemoteEmail(mixed $id)
|
2023-03-12 17:47:40 +01:00
|
|
|
{
|
2024-04-24 14:06:15 +02:00
|
|
|
return substr($id, 0, 184) . self::FAKE_REMOTE_DOMAIN;
|
2023-03-12 17:47:40 +01:00
|
|
|
}
|
|
|
|
|
2022-03-19 00:14:20 +01:00
|
|
|
/**
|
2022-11-22 15:15:52 +01:00
|
|
|
* {@inheritDoc}
|
|
|
|
*
|
2022-03-31 08:38:35 +02:00
|
|
|
* @codeCoverageIgnore
|
2022-03-19 00:14:20 +01:00
|
|
|
*/
|
|
|
|
public function retrieveByToken($identifier, $token)
|
|
|
|
{
|
2023-03-12 17:47:40 +01:00
|
|
|
throw new Exception(sprintf('No implementation for %s', __METHOD__));
|
2022-03-19 00:14:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2022-11-22 15:15:52 +01:00
|
|
|
* {@inheritDoc}
|
|
|
|
*
|
2022-03-31 08:38:35 +02:00
|
|
|
* @codeCoverageIgnore
|
2022-03-19 00:14:20 +01:00
|
|
|
*/
|
|
|
|
public function updateRememberToken(Authenticatable $user, $token)
|
|
|
|
{
|
|
|
|
throw new Exception(sprintf('No implementation for %s', __METHOD__));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2022-11-22 15:15:52 +01:00
|
|
|
* {@inheritDoc}
|
|
|
|
*
|
2022-03-31 08:38:35 +02:00
|
|
|
* @codeCoverageIgnore
|
2022-03-19 00:14:20 +01:00
|
|
|
*/
|
|
|
|
public function retrieveByCredentials(array $credentials)
|
|
|
|
{
|
2023-03-12 17:47:40 +01:00
|
|
|
throw new Exception(sprintf('No implementation for %s', __METHOD__));
|
2022-03-19 00:14:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2022-11-22 15:15:52 +01:00
|
|
|
* {@inheritDoc}
|
|
|
|
*
|
2022-03-31 08:38:35 +02:00
|
|
|
* @codeCoverageIgnore
|
2022-03-19 00:14:20 +01:00
|
|
|
*/
|
|
|
|
public function validateCredentials(Authenticatable $user, array $credentials)
|
|
|
|
{
|
2023-03-12 17:47:40 +01:00
|
|
|
throw new Exception(sprintf('No implementation for %s', __METHOD__));
|
2022-03-19 00:14:20 +01:00
|
|
|
}
|
2024-06-26 14:34:22 +02:00
|
|
|
|
|
|
|
/**
|
2024-07-03 11:16:08 +02:00
|
|
|
* {@inheritDoc}
|
2024-06-26 14:34:22 +02:00
|
|
|
*
|
2024-07-03 11:16:08 +02:00
|
|
|
* @codeCoverageIgnore
|
2024-06-26 14:34:22 +02:00
|
|
|
*/
|
|
|
|
public function rehashPasswordIfRequired(Authenticatable $user, array $credentials, bool $force = false)
|
|
|
|
{
|
|
|
|
throw new Exception(sprintf('No implementation for %s', __METHOD__));
|
|
|
|
}
|
2022-11-22 15:15:52 +01:00
|
|
|
}
|