Log data for Symfony Profiler - php

I created a Bundle that calls an third party api.
Now i want to show the received data in the Symfony Profiler.
I created a CustomDataCollector (http://symfony.com/doc/current/profiler/data_collector.html). That all works fine. But how can i get or "save" the received response for the api?
I created a service that calls the api with curl like that:
$raw_response = curl_exec($ch);
$response = json_decode($raw_response);
if (property_exists($response, 'error') && $response->errors) {
return ['status'=>false, 'msg'=> (string)$response->errors[0]->description ] ;
} else {
return ['status'=>true, 'msg' =>'Send Successfully' ];
}

I'd advise you to use the logger service for simple use-cases that don't require a specific collector. You can provide additional context to the logging:
/** LoggerInterface */
$container->get('logger')->error('There was an error on the API call.', array(
'description' => $response->errors[0]->description
);
The logger data is saved to a profile by default. For more advanced use cases you might be looking for the processors: http://symfony.com/doc/current/logging/processors.html

Related

Laravel handle Telegram webhooks

I'm fairly new to Laravel, and recently I tried to create a Telegram bot that can manage incoming messages and reply accordingly. Initially I plan to ask a user's name and use his name the next time the bot replies.
So how can I manage my bot's webhook which I already managed to set up.
Route::any('/setWebhook', function () {
$response = Telegram::setWebhook([
'url' => 'https://57f7-2806-104e-c-5c3b-3dc7-3284-7383-e130.ngrok.io/NdqvlJstHyIUhmNyTZhCYTnoYxdGzoPcLCzDiMiH/webhook'
]);
dd($response);
});
How can I manage the bot's incoming updates? I'm currently using irazasyed sdk.
You need to use a DB, which requires Model & migration
Telegram Bot API will send POST requests to your webhook
You should add ->middleware('api'), because you'll receive data
Use file_get_contents('php://input') to get the update, Or use a library.
To me, I use SimpleBotAPI library
Simple code in SimpleBotAPI:
// Handle updates here
class BotHandler extends UpdatesHandler
{
public function MessageHandler($message) : bool
{
// Do whatever:
$this->Bot->SendMessage(['chat_id' => $message->chat->id, 'text' => 'new Message!']);
return true;
}
}
Route::post('/bot_webhook', function () {
$Bot = new TelegramBot(env('BOT_TOKEN'), new BotHandler());
$Bot->OnWebhookUpdate();
})->middleware('api');

Laravel Nexmo invalid signature

I have SMS notification sending method via Nexmo client:
try {
$client = new Client(new SignatureSecret($nexmoKey, $signatureSecret, 'md5hash'));
$message = $client->message()->send(
[
'to' => $this->userNumber,
'from' => $from,
'text' => $this->notificationMessage,
'callback' => $webhookReceiveURL,
]
);
$response = $message->getResponseData();
$this->notificationId = $response['messages'][0]['message-id'];
return true;
} catch (\Exception $e) {
$this->exceptions[] = $e->getMessage();
return false;
}
If I put this piece of code in a service class where handle() method is called in Laravel's commands via crontab I get: Invalid Signature error but if I call this method from any controller method notification sends successfully. Can anyone explain why I get error if I try to send notification via crontab?
If the same code works in a controller, it sounds like configuration settings aren't getting passed into the job correctly. I would make sure that $nexmoKey and $signatureSecret look correct in the job.
On a side note, we do also offer a Laravel plugin through nexmo/laravel (https://github.com/Nexmo/nexmo-laravel/), which provides access to a Nexmo object via the Service Container and Facade layer. That may help cut down on the boilerplate for making the Nexmo object.

Drupal 8 external/custom authentication provider

I am experimenting with Drupal 8 as our customer websites. Our customers authenticate through our own authentication application at the moment which speaks to our document store (instead of MySQL) to authenticate a user and provide them with a unique session ID (JWT eventually but that's another day and conversation) which we can use to then query a REST API and get user data in any of our other self apps.
We are moving over from an old JSP based websites to drupal as our apps are now written in Symfony 3 but want our customer websites to be Drupal 8.
Here's the bit I am trying to work out. If I authenticate in our old website I want to be able to redirect to the Drupal 8 website with the session ID we have in our hand and use that to fetch a object back of our logged in user. I have this bit working fine but I now am in a position to say... Ok I have the user object back, the 3rd party service has said that session ID is valid so we know we are authenticated.
Please refer to the below flow chart. I want to be able to also authenticate in Drupal 8 manually. Is this possible (I am sure it is) and if so can someone point me in the right direction as to what I need/should be doing, API's I should be calling?
Thank you kindly and good day :)
You should use the External Auth module.
A good exemple of how use this module is the SimpleSamlPHP Auth
Ok so it turned out not to be that tricky in the end. I thought I would have to extend and implement various class and create my own provider (which is probably the best practice) but for KISS sake I found another way.
Create a user first if one does not exists based on the user data I get back from my external service. Then pass that created user to the user_login_finalize method (why are a lot of methods underscored Drupal...) which then authenticated my user.
public function inbound(Request $request)
{
// Point the guzzle client to our external session service.
$client = new GuzzleHttpClient([
'base_uri' => 'https://myexternalservice.com/apps/authentication/2/',
]);
// Attempt to send to request with the session ID from the parameters.
try {
$response = $client->request('GET', 'api/v1/user/' . $request->get('session_id'));
} catch (\Exception $e) {
throw new \HttpException($e->getMessage());
}
// Convert the response to an array.
$result = json_decode((string) $response->getBody(), true);
// Convert our array to a user entity.
if ($user = $this->convertResponseToUser($result['user'])) {
try {
// Attempt to load the user. If the user does not exist then create them first.
if (!$assumeUser = user_load_by_mail($user->getEmail())) {
// Create a Drupal user object.
$assumeUser = $this->createUser([
'name' => $user->getFirstName() . ' ' . $user->getLastName(),
'mail' => $user->getEmail()
]);
$assumeUser->save();
}
// Authenticate the user.
user_login_finalize($assumeUser);
} catch (\Exception $e) {
drupal_set_message(t('An unhandled exception occurred during authentication.'), 'error');
return $this->redirect('user.login');
}
}
return $this->redirect('mymodule.route');
}

LinkedIn returns 401: unknown authentication scheme when trying to share

I am trying to implement sharing to LinkedIn in our project. It works for me like a charm, however, for all of my colleagues, it does not. It returns 401: Unknown authentication scheme just for sharing request (profile requests work fine).
The LinkedIn app that we use is owned by me. For testing purposes another developer tried to create an app in his account, but the problem stayed: I was the only one who could share.
We are using linkedinapi/linkedin for back-end. Here's the code:
protected function openConnection()
{
$credentials = \Config::get('services.linkedin');
try
{
$this->connection = new \LinkedIn\LinkedIn([
'api_key' => $credentials['client_id'],
'api_secret' => $credentials['client_secret'],
'callback_url' => $credentials['redirect'],
]);
$this->connection->setAccessToken(\Auth::user()->linkedin->token['access_token']);
}
catch (\Exception $e)
{
\Log::error('Failed LinkedIn auth, exception is attached', [$e]);
throw new CouldNotPostException('Please, re-link your LinkedIn account, failed to send your post to LinkedIn.');
}
}
protected function send()
{
$object = [
'content' => [
'title' => $this->post->title,
'description' => \Str::limit($this->post->description, 253),
'submitted-url' => $this->post->shortlink,
'submitted_image_url' => \URL::to($this->post->image),
],
'comment' => $this->content,
'visibility' => [
'code' => 'connections-only'
]
];
try
{
$result = $this->connection->post('/people/~/shares?format=json', $object);
$this->posted($result['updateKey']);
}
catch (\Exception $e)
{
\Log::error('Failed LinkedIn posting, exception is attached', [$e]);
throw new CouldNotPostException('Failed to send your post to LinkedIn, our developers have been notified of this error.');
}
}
UPD: turns out it can post only on my machine, so there is something wrong with the configuration on their machines. Looking for it.
Investigation
I asked my colleague to login to LinkedIn on my machine, to see if posting fails for his account or for his computer. It posted, which showed that something is up with my configuration, that is why it works.
My next step was to re-install all of the vendor packages, including the mentioned above linkedinapi/linkedin. After that posting stopped working for me as well. After inspecting the way that library signs requests, I found that it does not match the way LinkedIn requires it. The library was including a oauth2_access_token parameter in the URL, but LinkedIn expects an Authorization HTTP header as it is stated in their documentation:
Once you've obtained an Access Token, you can start making authenticated API requests on behalf of the user. This is accomplished by including an "Authorization" header in your HTTP call to LinkedIn's API.
Solution
So for now I changed the way I make the request. Instead of
$result = $this->connection->post('/people/~/shares?format=json', $object);
I use a different function that allows me to include the header manually:
$result = $this->connection->fetch(
'/people/~/shares?format=json',
$object,
\LinkedIn\LinkedIn::HTTP_METHOD_POST,
[ 'Authorization: Bearer ' . $this->connection->getAccessToken() ]
);
Also, I created a pull request to the repository.

Laravel API to returns json response

I'm developing and College project, It should be a platform that serve and Web and Mobile Front-En. I decided to use Laravel 5.1, my idea was to use laravel as an excelent hardcore php backend to serve this platform, I wanted to develope APIsRest with laravel and comsume the services on both web and mobile front-end. My point is: I don't wanna use blade templating engine, because returning "views, instance objects, etc" my mobile front won't understand responses, that's why I want to orientated my APIs to return JSONs messanges, so I can handle them on each front.
1) First at all I wanna ask you guys if is it a good idea?
2) how can I retrieve the error php messages send by laravel to send them back to views (mobile-web front) as JSONs?
Example: Right now I'm trying to finish the "Login-Register" module of my project. I'm trying to use the advantages of Authentication Laravel Module, and now I am stack on postLogin, because i don't know how to handle the error and send it back to front as JSON.
public function postIngresar(Request $request)
{
$throttles = $this->isUsingThrottlesLoginsTrait();
if ($throttles && $this->hasTooManyLoginAttempts($request)) {
return response()->json(*$this->sendLockoutResponse($request));
}
$credentials = $this->getCredentials($request);
if (Auth::attempt($credentials, $request->has('remember'))) {
return response()->json([
'success' => 'true',
'message' => 'Logeo logrado exitosamente'
]);
}
if ($throttles) {
$this->incrementLoginAttempts($request);
}
return response()->json($this->getFailedLoginMessage());
}
is there any way to handle all error and exception as JSON messages? It'll will help me A LOT.
thank you so much by reading.
You can read about Exception Handling section of the Laravel docs, but to save you the time, here is the name of the method that will be responsible for returning json representation of your errors:
All exceptions are handled by the App\Exceptions\Handler class. This class contains two methods: report and render. The render method is responsible for converting a given exception into an HTTP response that should be sent back to the browser. By default, the exception is passed to the base class which generates a response for you. However, you are free to check the exception type or return your own custom response
The LoginController uses the AuthenticatesUsers trait which has a method sendFailedLoginResponse which is responsible for the error message redirect upon authentication failure as follows:
protected function sendFailedLoginResponse(Request $request)
{
if ( ! User::where('email', $request->email)->first() ) {
return response()->json([
$this->username() => Lang::get('auth.email')
]);
}
if ( ! User::where('email', $request->email)->where('password', bcrypt($request->password))->first() ) {
return response()->json([
'password' => Lang::get('auth.email')
]);
}
}

Categories