Laravel with Linkedin API error - ServiceFactory::createService() must be an instance of OAuth\Common\Storage\TokenStorageInterface - api

I'm using Laravel to develop my website, and I integrated the linkedin login to it, it works fine for like a few months. then suddenly, last week i received an error. I didn't change any code that has something to do with Linkedin API. I'm suspecting whether it has something to do with Linkedin itself.
here's what the error looks like:

If you are using this library to integrate Linkedin to your laravel project, there might be an issue right now with the update. you can simply fix the error in OAuth.php by replacing it with this code:
<?php namespace Artdarek\OAuth;
/**
* #author Dariusz Prząda <artdarek#gmail.com>
* #copyright Copyright (c) 2013
* #license http://www.opensource.org/licenses/mit-license.html MIT License
*/
use \Config;
use \URL;
use \OAuth\ServiceFactory;
use \OAuth\Common\Consumer\Credentials;
class OAuth {
/**
* #var ServiceFactory
*/
private $_serviceFactory;
/**
* Storege name from config
*
* #var string
*/
private $_storage_name = 'Session';
/**
* Client ID from config
*
* #var string
*/
private $_client_id;
/**
* Client secret from config
*
* #var string
*/
private $_client_secret;
/**
* Scope from config
*
* #var array
*/
private $_scope = [];
/**
* Constructor
*
* #param ServiceFactory $serviceFactory - (Dependency injection) If not provided, a ServiceFactory instance will be constructed.
*/
public function __construct(ServiceFactory $serviceFactory = null)
{
if (null === $serviceFactory)
{
// Create the service factory
$serviceFactory = new ServiceFactory();
}
$this->_serviceFactory = $serviceFactory;
}
/**
* Detect config and set data from it
*
* #param string $service
*/
public function setConfig($service)
{
// if config/oauth-4-laravel.php exists use this one
if (Config::get('oauth-5-laravel.consumers') != null)
{
$this->_storage_name = Config::get('oauth-5-laravel.storage', 'Session');
$this->_client_id = Config::get("oauth-5-laravel.consumers.$service.client_id");
$this->_client_secret = Config::get("oauth-5-laravel.consumers.$service.client_secret");
$this->_scope = Config::get("oauth-5-laravel.consumers.$service.scope", []);
// esle try to find config in packages configs
}
else
{
$this->_storage_name = Config::get('oauth-5-laravel::storage', 'Session');
$this->_client_id = Config::get("oauth-5-laravel::consumers.$service.client_id");
$this->_client_secret = Config::get("oauth-5-laravel::consumers.$service.client_secret");
$this->_scope = Config::get("oauth-5-laravel::consumers.$service.scope", []);
}
}
/**
* Create storage instance
*
* #param string $storageName
*
* #return OAuth\Common\\Storage
*/
public function createStorageInstance($storageName)
{
$storageClass = "\\OAuth\\Common\\Storage\\$storageName";
$storage = new $storageClass();
return $storage;
}
/**
* Set the http client object
*
* #param string $httpClientName
*
* #return void
*/
public function setHttpClient($httpClientName)
{
$httpClientClass = "\\OAuth\\Common\\Http\\Client\\$httpClientName";
$this->_serviceFactory->setHttpClient(new $httpClientClass());
}
/**
* #param string $service
* #param string $url
* #param array $scope
*
* #return \OAuth\Common\Service\AbstractService
*/
public function consumer($service, $url = null, $scope = null)
{
// get config
$this->setConfig($service);
// get storage object
$storage = $this->createStorageInstance($this->_storage_name);
// create credentials object
$credentials = new Credentials(
$this->_client_id,
$this->_client_secret,
$url ? : URL::current()
);
// check if scopes were provided
if (is_null($scope))
{
// get scope from config (default to empty array)
$scope = $this->_scope;
}
// return the service consumer object
return $this->_serviceFactory->createService($service, $credentials, $storage, $scope);
}
}

Related

Laravel 5.8 : manage failed mail notifications from a queue

I'm a little confused about the management of mail notifications failed from a queue.
I've created a mail notification class that I use to send a same notification to multiple users.
The process works well, but i'm trying to set up a management for the notifications that would fail (like sending a mail to the admin users to alert them about the failed notifications).
Here is the mail notification class :
class MyCustomMailNotification extends Notification implements
ShouldQueue {
use Queueable;
/**
* The number of times the job may be attempted.
*
* #var int
*/
public $tries = 3;
/**
* The number of seconds the job can run before timing out.
*
* #var int
*/
//public $timeout = 90;
/**
* Create a new notification instance.
*
* #return void
*/
public function __construct()
{
//
}
/**
* Get the notification's delivery channels.
*
* #param mixed $notifiable
* #return array
*/
public function via($notifiable)
{
return ['mail'];
}
/**
* Get the mail representation of the notification.
*
* #param mixed $notifiable
* #return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)
->subject('My Subject')
->greeting('My greeting')
->line('My mail body')
->salutation('My salutations');
}
/**
* Get the array representation of the notification.
*
* #param mixed $notifiable
* #return array
*/
public function toArray($notifiable)
{
return [
//
];
}
public function failed(Exception $e)
{
dd('Entered failed from MyCustomMailNotification : ' . $e));
}
}
I've set a listener "LogNotification" To reach the handle of notification event, with a specific instruction to generate a fail :
EventServiceProvider:
/**
* The event listener mappings for the application.
*
* #var array
*/
protected $listen = [
'Illuminate\Notifications\Events\NotificationSent' => [
'App\Listeners\LogNotification',
],
];
Listener:
namespace App\Listeners;
use Illuminate\Notifications\Events\NotificationSent; use
Illuminate\Queue\InteractsWithQueue; use
Illuminate\Contracts\Queue\ShouldQueue;
class LogNotification {
/**
* Create the event listener.
*
* #return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* #param NotificationSent $event
* #return void
*/
public function handle(NotificationSent $event)
{
$result = 1/0;
}
}
The mailing is made in a controller like this:
$when = Carbon::now()->addSeconds(5);
foreach ($users as $user) {
$user->notify((new MyCustomMailNotification())->delay($when));
}
As in the failed function, I don't get any information of the notification that has failed, my question is:
How can I related a failure with the notification that has failed?
The goal is to be able to get the information of the user who has therefore not received his notification email.
Thanks for any help, idea or solution!
Well, that was so simple that I didn't see it...
As the failed function is inside the notification class, I can related to the notification simply with:
$this->id
And then of course get all the informations about the notification from model/table like user id (notifiable_id) and data field with custom informations.

PDOException: SQLSTATE[HY000] [2054] The server requested authentication method unknown to the client (Bitbucket pipeline)

I'm running a bitbucket pipeline to execute all the unit test with PHP Unit. When I execute the test on local all of them pass. But on the bitbucket pipeline it always fail. In this case, the tests are related to an external service that we are checking.
<?php
namespace Tests\Unit;
use Tests\TestCase;
use Illuminate\Foundation\Testing\RefreshDatabase;
use MyService;
class MyTest extends TestCase
{
/**
* Test the dummies in this new system
*
* #return void
*/
public function testDumies()
{
$games = DummyService::getDummies();
$this->assertTrue(count($dummies) > 0);
}
public function testDummiesOfUser()
{
$dummies = DummyService::getDummiesOfUser('someemail#mail.com');
$this->assertTrue(count($dummies) > 0);
}
}
And the following is the service to get the dummies
<?php
namespace App\Services;
class DummyService {
/**
* Get dummies
*
* #return void
*/
public function getDummies() {
$collection = [];
$games = $this->getDummiesInUrl('http://my-project/api/v1/platform/dummies');
foreach($dummies as $dummy) {
$collection[] = $dummy;
}
return $collection;
}
/**
* Retrieves the dummies in url
*
* #param string $endpoint
* #return array
*/
public function getDummiesInUrl($endpoint) {
$client = new \GuzzleHttp\Client();
$res = $client->request('GET', $endpoint);
$body = $res->getBody();
$body = json_decode($body, true);
$data = $body['data'];
$dummies = $data['dummies'];
return $dummies;
}
/**
* Returns the dummies of an user
*
* #param string $email
* #return array
*/
public function getDummiesOfUser($email) {
$collection = [];
$dummies = $this->getDummiesOfUserInUrl('http://myroute/api/v1/platform/dummies/user', $email);
foreach($dummies as $d) {
$collection[] = $d;
}
return $collection;
}
/**
* Get gameplays in url
*
* #param string $endpoint
* #param string $email
* #return array
*/
public function getDummiesOfUserInUrl($endpoint, $email) {
$client = new \GuzzleHttp\Client();
$res = $client->request('GET', $endpoint, ['query' => ['email' => $email]]);
$body = $res->getBody();
$body = json_decode($body, true);
$data = $body['data'];
$dummies = $data['dummiess'];
return $dummies;
}
}
But when that is tested on the bitbucket pipeline I got the following errors:
PDOException: SQLSTATE[HY000] [2054] The server requested authentication method unknown to the client and Caused by PDOException:PDO::__construct(): The server requested authentication method unknown to the client [caching_sha2_password]
Apparently with the new public version of mysql 8, lots of things have changed. So in order to keep working with your pipelines, I edited my bitbucket-pipelines.yml and changed the mysql image version from mysql to mysql:5.7.22
definitions:
services:
mysql:
image: mysql:5.7.22
environment:
MYSQL_DATABASE: 'homestead'
MYSQL_RANDOM_ROOT_PASSWORD: 'yes'
MYSQL_USER: 'homestead'
MYSQL_PASSWORD: 'secret'

zend expressive - zend db

I'm trying to use zend expressive and looking at how to do database stuff now. I was looking at this, but it's not clear. I used composer to install zend-db and it mentioned to add a line in dependencies.global.php and then use container in the factory class to get the adapter but then didn't talk about how to access it in the actual action class so I don't know what's going on as the adapter object is out of scope from other class.
Anyone has good and clear example from start to finish to actually able to connect and query sql?
try to inject your db class via factory, follow example on skeleton app, you can do something like this:
HomePageFactory.php
public function __invoke(ContainerInterface $container)
{
$router = $container->get(RouterInterface::class);
$template = $container->has(TemplateRendererInterface::class) ? $container->get(TemplateRendererInterface::class) : null;
$adapter = $container->get( Adapter::class );
$usersTable = $container->get( Table\UsersTable::class );
return new HomePageAction($router, $template,$adapter,$usersTable);
}
HomePageAction.php
class HomePageAction implements ServerMiddlewareInterface
{
/**
* #var Router\RouterInterface
*/
private $router;
/**
* #var null|Template\TemplateRendererInterface
*/
private $template;
/**
* #var Adapter
*/
private $dbAdapter;
/**
* #var UsersTable
*/
private $usersTable;
/**
* HomePageAction constructor.
* #param Router\RouterInterface $router
* #param Template\TemplateRendererInterface|null $template
* #param Adapter $adapter
* #param UsersTable $usersTable
*/
public function __construct( Router\RouterInterface $router, Template\TemplateRendererInterface $template = null, Adapter $adapter, Table\UsersTable $usersTable )
{
$this->router = $router;
$this->template = $template;
$this->dbAdapter = $adapter;
$this->usersTable = $usersTable;
}
on your config provider where you have your tables u have to config dependencies as factory EX:
'factories' => [
Table\UsersTable::class => function($container) {
$dbAdapter = $container->get( AdapterInterface::class );
$resultSetPrototype = new ResultSet();
$resultSetPrototype->setArrayObjectPrototype( new Model\Users() );
$tableGateway = new TableGateway('users', $dbAdapter, null, $resultSetPrototype);
return new Table\UsersTable($tableGateway);
},
],

Laravel Auth Custom Driver Error

FYI : I'm very new to Laravel and doing my best to learn it properly.
Working on an auth driver that uses a soap service to authenticate.
Error I get when trying to test with Auth::attempt()
Symfony \ Component \ Debug \ Exception \ FatalErrorException (E_COMPILE_ERROR)
Declaration of Project\Providers\AuthUserProvider::retrieveByToken() must be compatible with Illuminate\Auth\UserProviderInterface::retrieveByToken($identifier, $token)
Here is the driver...
<?php namespace Project\Providers;
use Illuminate\Auth\UserProviderInterface;
use Illuminate\Auth\GenericUser;
use Illuminate\Auth\UserInterface;
class AuthUserProvider implements UserProviderInterface {
/**
* External webservice for authentication
*/
private $webservice;
/**
* The user object.
*/
private $user;
/**
* Constructor
*
* #return void
*/
public function __construct(\Project\Webservice\AuthCheckApi $webservice)
{
$this->webservice = $webservice;
$this->user = null;
}
/**
* Retrieves a user by id
*
* #param int $identifier
* #return mixed null|array
*/
public function retrieveByID($identifier)
{
$this->user = is_null($this->user) ? $this->webservice->find($identifier) : $this->user;
return $this->user;
}
/**
* Tries to find a user based on the credentials passed.
*
* #param array $crendtials username|password
* #return mixed bool|UserInterface
*/
public function retrieveByCredentials(array $credentials)
{
if(!$user = $this->webservice->byusername($credentials['username'],$credentials['password'])) return false;
return new GenericUser($user);
}
/**
* Validates the credentials passed to the ones in webservice.
*
* #param UserInterface $user
* #param array $credentials
* #return bool
*/
public function validateCredentials(\Illuminate\Auth\UserInterface $user, array $credentials)
{
$validated = $this->webservice->validateCredentials($user,$credentials['username']);
return true;
}
/**
* Needed by Laravel 4.1.26 and above
*/
public function retrieveByToken()
{
return true;
}
/**
* Needed by Laravel 4.1.26 and above
*/
public function updateRememberToken()
{
return false;
}
}
Thanks for any help.
You are implementing the UserProviderInterface so you need to add the complete definition of all functions of the interface, here you are forgetting the arguments for the last two function
public function retrieveByToken($identifier, $token)
{
}
public function updateRememberToken($user, $token)
{
}

Symfony2-Doctrine: ManyToMany bi-directionnal relation

I've already search a lot befors asking, even the related topic Symfony2-Doctrine: ManyToMany relation is not saved to database
but still no answer.
I've got this two classes:
class Intervenant extends User
{
/**
* #ManyToMany(targetEntity="iMDEO\DISAASBundle\Entity\Domaine", inversedBy="intervenants", cascade={"persist","merge"})
*/
private $domaines;
/**
* Add domaines
*
* #param Domaine $domaines
*/
public function addDomaine(Domaine $domaines)
{
$this->domaines[] = $domaines;
}
/**
* Get domaines
*
* #return Doctrine\Common\Collections\Collection
*/
public function getDomaines()
{
return $this->domaines;
}
}
class Domaine
{
// ...
/**
* #ORM\ManyToMany(targetEntity="Intervenant", mappedBy="domaines", cascade={"persist","merge"})
*
*/
private $intervenants;
/**
* Add intervenants
*
* #param Intervenant $intervenants
*/
public function addIntervenant(Intervenant $intervenants)
{
$intervenants->addDomaine($this);
$this->intervenants[] = $intervenants;
}
/**
* Get intervenants
*
* #return Doctrine\Common\Collections\Collection
*/
public function getIntervenants()
{
return $this->intervenants;
}
}
When I save an Intervenant, everthing is OK.
But when i save the inverse side Domaine, the changes are not persisted.
Reading Symfony's doc and topics everywhere, I can't find any solution to get a bi-directionnal relation between my two entities.
Here's part of my DomaineController:
$em = $this->getDoctrine()->getEntityManager();
$entity = $em->getRepository('myBundle:Domaine')->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find Domaine entity.');
}
$editForm = $this->createForm(new DomaineType(), $entity);
$deleteForm = $this->createDeleteForm($id);
$request = $this->getRequest();
$editForm->bindRequest($request);
if ($editForm->isValid()) {
$em->persist($entity);
$em->flush();
return $this->indexAction();
}
// ...
My purpose is that when I create/edit an Intervenant, I can choose related Domaine.
And when I create/edit a Domaine, I link every Intervenants in it.
Could you please help me?