This commit is contained in:
Maxime Renou 2020-05-11 17:54:18 +02:00
parent 3269a7d151
commit 6dbc2ee43e
2 changed files with 112 additions and 25 deletions

View File

@ -5,6 +5,7 @@ namespace Bluesquare\Connect;
use Bluesquare\Connect\Traits\HasConnectSync; use Bluesquare\Connect\Traits\HasConnectSync;
use GuzzleHttp\Client; use GuzzleHttp\Client;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Psr\Http\Message\StreamInterface; use Psr\Http\Message\StreamInterface;
@ -42,10 +43,10 @@ class Connect
* @param $method * @param $method
* @param $uri * @param $uri
* @param null $data * @param null $data
* @return \Psr\Http\Message\StreamInterface * @return array
* @throws ConnectException * @throws ConnectException
*/ */
public function request($method, $uri, $data = null, $auth = true): StreamInterface public function request($method, $uri, $data = null, $auth = true): array
{ {
$url = $this->getUrl(); $url = $this->getUrl();
$url = $url . '/' . trim($uri, '/'); $url = $url . '/' . trim($uri, '/');
@ -106,20 +107,82 @@ class Connect
return redirect()->to($url); return redirect()->to($url);
} }
public function getAccessTokenFromAuhtorizationCode($code)
{
$data = $this->request('post', 'oauth/token', [
'grant_type' => 'authorization_code',
'client_id' => config('bconnect.client_id'),
'client_secret' => config('bconnect.client_secret'),
'scope' => config('bconnect.user_scopes'),
'redirect_uri' => config('bconnect.redirect_url'),
'code' => $code
], false);
return $data;
}
public function getAccessTokenFromRefreshToken($refresh_token)
{
$data = $this->request('post', 'oauth/token', [
'grant_type' => 'refresh_token',
'client_id' => config('bconnect.client_id'),
'client_secret' => config('bconnect.client_secret'),
'scope' => config('bconnect.user_scopes'),
'redirect_uri' => config('bconnect.redirect_url'),
'refresh_token' => $refresh_token
], false);
return $data;
}
public function getUserData($access_token)
{
return $this->request('get', 'api/user', null, $access_token);
}
public function updateUserConnectData($model, $data)
{
$model->connect_access_token = $data['access_token'];
$model->connect_refresh_token = $data['refresh_token'];
$model->connect_expires_at = $data['expires_at'];
$model->save();
}
public function getUserAccessToken($model)
{
if (empty($model->connect_access_token) || empty($model->connect_refresh_token) || empty($model->connect_expires_at)) {
throw new ConnectException("Missing Bluesquare Connect attributes on model: connect_access_token, connect_refresh_token, connect_expires_at");
}
if ($model->connect_expires_at <= now()) {
$connect_data = $this->getAccessTokenFromRefreshToken($model->connect_refresh_token);
$this->updateUserConnectData($model, $connect_data);
return $connect_data['access_token'];
}
return $model->connect_access_token;
}
public function loginFromCallback(Request $request) public function loginFromCallback(Request $request)
{ {
// State check // State check
if (!session()->has('connect_states')) if (!session()->has('connect_states')) {
abort(403, "Session expired"); Log::debug("Missing session states");
return redirect('/');
}
$states = session()->get('connect_states'); $states = session()->get('connect_states');
if (!is_array($states)) if (!is_array($states)) {
abort(403, "Session expired"); Log::debug("Invalid session state");
return redirect('/');
}
if (!$request->has('state') || !in_array($request->state, $states)) if (!$request->has('state') || !in_array($request->state, $states)) {
abort(403, "Invalid state"); Log::debug("Missing valid state in request");
return redirect('/');
}
unset($states[array_search($request->state, $states)]); unset($states[array_search($request->state, $states)]);
@ -127,22 +190,26 @@ class Connect
// Code check // Code check
if (!$request->has('code')) if (!$request->has('code')) {
abort(403, "Missing authorization code"); Log::debug("Missing authorization code");
return redirect('/');
$code = $request->code; }
// Access token // Access token
$expires_at = now();
$connect_data = $this->getAccessTokenFromAuhtorizationCode($request->code);
$connect_data['expires_at'] = $expires_at->addSeconds($connect_data['expires_in']);
$data = $this->request('post', 'oauth/token', [ $model_data = $this->getUserData($connect_data['access_token']);
'grant_type' => 'authorization_code',
'client_id' => config('bconnect.client_id'),
'client_secret' => config('bconnect.client_secret'),
'scope' => config('bconnect.user_scopes'),
'code' => $code
], false);
return $data; $this->sync('User', $model_data['id']);
$model = $this->synchronized['User'];
$user = $model::findOrFail($model_data['id']);
$this->updateUserConnectData($user, $connect_data);
return $user;
} }
// OAuth (client) // OAuth (client)
@ -222,6 +289,8 @@ class Connect
foreach ($resourceTypes as $resourceType) foreach ($resourceTypes as $resourceType)
{ {
$resourceType = $this->resolveResourceType($resourceType);
if (!array_key_exists($resourceType, $this->synchronized)) if (!array_key_exists($resourceType, $this->synchronized))
throw new ConnectException("Resource $resourceType not declared as synchronized."); throw new ConnectException("Resource $resourceType not declared as synchronized.");
@ -245,6 +314,8 @@ class Connect
public function sync($resourceType, $resourceId, $resourceData = null) public function sync($resourceType, $resourceId, $resourceData = null)
{ {
$resourceType = $this->resolveResourceType($resourceType);
if (is_null($resourceData)) { if (is_null($resourceData)) {
$resourceData = $this->get($resourceType, $resourceId); $resourceData = $this->get($resourceType, $resourceId);
} }
@ -257,6 +328,22 @@ class Connect
// //
protected function resolveResourceType($class)
{
if (in_array($class, $this->synchronized))
return array_flip($this->synchronized)[$class];
return $class;
}
protected function resolveResourceModel($class)
{
if (array_key_exists($class, $this->synchronized))
return $this->synchronized[$class];
return $class;
}
protected function getEventMethod($event) protected function getEventMethod($event)
{ {
return 'onConnectResource' . ucfirst($event); return 'onConnectResource' . ucfirst($event);

View File

@ -4,7 +4,7 @@ namespace Bluesquare\Connect\Traits;
trait HasConnectSync trait HasConnectSync
{ {
abstract function fill($data); abstract function fill(array $attributes);
abstract function save(); abstract function save();
abstract function delete(); abstract function delete();