So i'm working on this Laravel application which uses ratchet for the websockets, and I want to get the current users session in my websocket controller. Previously I was working with Laravel 5.2 and this code worked great
public function onOpen(ConnectionInterface $conn) {
$session = (new SessionManager(App::getInstance()))->driver();
$cookies = $conn->WebSocket->request->getCookies();
if(!empty($cookies)){
$laravelCookie = urldecode(isset($cookies[Config::get('session.cookie')]) ? $cookies[Config::get('session.cookie')] : '');
if(!empty($laravelCookie)){
$idSession = Crypt::decrypt($laravelCookie);
$session->setId($idSession);
$conn->session = $session;
}
}
$newConnection = new \stdClass();
$newConnection->resourceId = $conn->resourceId;
$newConnection->conn = $conn;
$this->clients[] = $newConnection;
$newConnection->conn->send(json_encode(['status' => 'success', 'message' => 'Response from server, successful']));
}
After the user has connected, I just load the current session when ever the user sends a message
public function onMessage(ConnectionInterface $from, $msg) {
$user = [];
$request = json_decode($msg);
if(isset($from->session)){
$from->session->start();
$idUser = $from->session->get(Auth::getName());
QLog::info($idUser);
if (isset($idUser)) {
$user = User::find($idUser);
}
$from->session->save();
}
if($request->action == 'get-user' && $user){
$this->clients[0]->conn->send(json_encode(['username' => $user->getFullName()]));
} else {
$this->clients[0]->conn->send(json_encode(['username' => 'not found']));
}
}
But now I need to do the same thing in Laravel 4.2, but as it turns out, that in Laravel 4.2 there is no method getInstance(). What would be the best alternative to use in my situation?
This seems to work:
$app = App::getFacadeApplication();
I couldn't find any references to doing this, but figured it out via the Facade interface. So I don't know if this is good practise or not. I'm using it because I use Illuminate outside of Laravel.
Related
I have tried using old v4.9 endpoints that haven't been replaced by v1 so far such as:
https://developers.google.com/my-business/reference/rest/v4/accounts.locations/reportInsights
https://developers.google.com/my-business/reference/rest/v4/accounts.locations.reviews
However, none of these endpoints work anymore.
I am using PHP client that had these endpoints missing, but using the official v4.9 library listed here: https://developers.google.com/my-business/samples/previousVersions I have been able to reach some of the old endpoints such as reviews.
However they no longer return any data or data object is empty.
Anyone has experienced similar issues?
The v4.9 (not yet deprecated) endpoints such as reviews, insights etc. are working, but the official library is broken and botched.
I had to code a replacement using Guzzle client reaching to the endpoints directly instead. So you need to code the API library yourself from scratch for these v4.9 endpoints as the official library does not work.
How to fetch reviews:
public static function listReviews($client, $params, $account, $location)
{
$response = $client->authorize()->get('https://mybusiness.googleapis.com/v4/' . $account . '/' . $location . '/reviews', ['query' => $params]);
return json_decode((string) $response->getBody(), false);
}
How to fetch insights:
/** v4.9 working 02/2022 **/
public static function reportInsights($client, $params, $account)
{
try {
$response = $client->authorize()->post('https://mybusiness.googleapis.com/v4/' . $account . '/locations:reportInsights', [
\GuzzleHttp\RequestOptions::JSON => $params,
]);
} catch (\GuzzleHttp\Exception\RequestException $ex) {
return $ex->getResponse()->getBody()->getContents();
}
return json_decode((string) $response->getBody(), false);
}
How to prepare payload for insights:
$params = new \stdClass();
$params->locationNames = $account->name . '/' . $location->name;
$time_range = new \stdClass();
$time_range->startTime = Carbon::parse('3 days ago 00:00:00')->toISOString();
$time_range->endTime = Carbon::parse('2 days ago 00:00:00')->toISOString();
if ($force == 'complete') {
$time_range->startTime = Carbon::parse('17 months ago 00:00:00')->toIso8601ZuluString();
$time_range->endTime = Carbon::parse('3 days ago 00:00:00')->toIso8601ZuluString();
}
$params->basicRequest = new \stdClass();
$params->basicRequest->timeRange = $time_range;
$params->basicRequest->metricRequests = new \stdClass();
$metric_request = new \stdClass();
$metric_request->metric = 'ALL';
$metric_request->options = ['AGGREGATED_DAILY'];
$params->basicRequest->metricRequests = [
$metric_request,
];
Note: if you are getting empty insights response, you have to check verification using new v1 API call such as:
$verifications = \Google_Service_MyBusinessVerifications($client)->locations_verifications->listLocationsVerifications($location->getName());
$verification = '0';
if ($verifications->getVerifications()) {
$verification = $verifications->getVerifications()[0]->getState();
}
Using official API client with an existing token (needs to be fetched via OAuth2):
$provider = new GoogleClientServiceProvider(true);
$client = $provider->initializeClient($known_token, ['https://www.googleapis.com/auth/plus.business.manage', 'https://www.googleapis.com/auth/drive']);
I found a post on Laravel.io on how to load Laravel sessions into Ratchet which is outdated and uses Laravel 5.4 so I've altered a few things to get this to work with Laravel 8.x
public function onOpen(ConnectionInterface $conn)
{
// Attach connection
$this->clients->attach($conn);
// Create a new session handler for this client
$session = (new SessionManager(App::getInstance()))->driver();
// Get the cookies
$cookiesRaw = $conn->httpRequest->getHeader('Cookie');
$cookies = [];
if(count($cookiesRaw)) {
$cookies = Header::parse($cookiesRaw)[0]; // Array of cookies
}
// Get the laravel's one - todo: try catch
$sessionId = Crypt::decrypt(urldecode($cookies[Config::get('session.cookie')]), false);
var_dump($sessionId);
// Set the session id to the session handler
$session->setId($sessionId);
// Bind the session handler to the client connection
$conn->session = $session;
var_dump($conn->session->getId());
}
I then altered the send message too because I am receiving unexpected results.
public function onMessage(ConnectionInterface $conn, MessageInterface $msg)
{
$conn->session->start();
$sessionId = $conn->session->getId();
var_dump($sessionId);
if(!is_null(($decoded = json_decode(base64_decode($msg), true))) && array_diff(['message'], array_keys($decoded)))
return;
var_dump($decoded['message']);
return;
}
I test this with JS front-end like so:
class WebRTC
{
socket;
constants;
timerId;
constructor(protocol, fqdns, port) {
this.constants = {
protocol: protocol,
fqdns: fqdns,
port: port
};
this.listenChanges();
}
listenChanges() {
this.socket = new WebSocket(`${this.constants.protocol}://${this.constants.fqdns}:${this.constants.port}`);
this.socket.onmessage = e => {
console.log(atob(e.data));
};
this.socket.onerror = () => {
this.socket.close();
};
this.socket.onopen = () => {
console.info('Connected to WebRTC Chat Server...');
this.socket.send(btoa(JSON.stringify({
message: '{{ session()->getId() }}' // Expected session
})));
clearInterval(this.timerId);
this.socket.onclose = () => {
this.timerId = setInterval(() => {
this.listenChanges();
}, 1000);
};
};
}
}
new WebRTC('ws', '127.0.0.1', '8080');
& When the connection opens, I sent the session()->getId() which is the expected session I need. However, my output in the CLI is:
onOpen() : $sessionId
string(81) "b0e41cf0d856bdfc8427e1fdde62d5a154519f9c|MLXa9H2BbnQmySt2hRB360UANxLGHyz6iRMxGcoG"
onOpen() : $conn->session->getId()
string(40) "qyaDOQjNFlbrbjvvKRE1m5sN0dsGqqAsoMfkeqyU"
onMessage(): $conn->session->getId()
string(40) "qyaDOQjNFlbrbjvvKRE1m5sN0dsGqqAsoMfkeqyU"
JS blade formatted actual session that is sent as a message
string(40) "MLXa9H2BbnQmySt2hRB360UANxLGHyz6iRMxGcoG"
Here, my expected onMessage() method receive the dependency injected $conn (ConnectionInterface) with the ->session->getId() of the actual session()->getId() so I can make Auth::user() work.
Any ideas on what I'm doing wrong? I tried the var_dump($conn->session->get(Auth::getName())); as the Laravel.Io says to do but it returns null on the var_dump and my user is logged in.
This should then give me access to use User::find() or Auth::user().
Twinfield is an online financial accounting software package for small and medium enterprises, produced and maintained by Twinfield International, based in The Netherlands. It is used by over 15,000 subscribers in 20 countries.
I want to integrate its API. I have install laravel and create some basic API, but its huge. How and where the integration example links? Please help me.
This is not the full code but gives you the login for the twinfield. I am also stuck because many libraries are given for twinfield but not give any sample code for it. There is no document provide for PHP integration. I am very disappointed with twinfield. Even if you have test account and it will disable than it will permanent disable. Here the jsonresponse is custom made so you can call only $e->getMessage() if you have any error related it.
public function login(\Illuminate\Http\Request $request){
$user = $request->input('user');
$password = $request->input('password');
$org = $request->input('organisation');
$params = array(
'user' => $user,
'password' => $password,
'organisation' => $org
);
// login => Set the param array and send to the logon
try
{
$session = new \SoapClient("https://login.twinfield.com/webservices/session.asmx?wsdl", array('trace' => 1));
$result = $session->logon($params);
// echo '<pre>';print_r($result);
$cluster = $result->cluster;
$qq = new domDocument();
$qq->loadXML($session->__getLastResponse());
$sessionID = $qq->getElementsByTagName('SessionID')->item(0)->textContent;
//echo $sessionID;
$newurl = $cluster . '/webservices/processxml.asmx?wsdl';
try
{
$client = new \SoapClient($newurl);
$data = new \SoapHeader('http://www.twinfield.com/', 'Header', array('SessionID'=> $sessionID));
$jsonResponse = JsonResponse::success($data);
}
catch (SoapFault $e)
{
$jsonResponse = empty($e->getMessage()) ? JsonResponse::error(class_basename($e)) : JsonResponse::error($e->getMessage());
}
}
catch (SoapFault $e)
{
$jsonResponse = empty($e->getMessage()) ? JsonResponse::error(class_basename($e)) : JsonResponse::error($e->getMessage());
}
return $jsonResponse;
}
Some code are given in this link too. You will integrate it via https://github.com/php-twinfield/twinfield but you have to work a lot. I am also working on it, if anything you need plz let me know.
Could you please help me,
My code is not saving SESSION between requests.
when i Login, it always returns null in session.
Thank you in advance.
$app->get('/session', function($request, $response, $args) {
$session = new \SlimSession\Helper;
$reponse["uid"] = $session->uid;
$reponse["email"] = $session->email;
$reponse["name"] = $session->name;
echo json_encode($reponse);
});
$app->post('/connexion', function ($request, $response, $args) {
$reponse['status'] = "success";
$reponse['message'] = 'Vous ĂȘtes connectĂ©.';
$reponse['name'] = "wassim boukadida";
$reponse['uid'] = "123456";
$reponse['email'] = "test#test.com";
$reponse['createdAt'] = "date_exmple";
//session saving
$session = new \SlimSession\Helper;
$session->uid = "123456";
$session->email = "test#test.com";
$session->name = "wassim boukadida";
echo json_encode($reponse);
});
You need to start the session, bryanjhv/slim-session has already middleware for that, which you just need to add:
$app = new \Slim\App;
// add the middleware
$app->add(new \Slim\Middleware\Session());
// add routes
$app->run();
For settings look at the readme file of bryanjhv/slim-session as this helper is currently in development
I'm writing unit tests for my application. I wrote a function to login different user (to test user levels) and a function to generate valid or invalid form data (to test my form handling).
When the test submits a form, it throws an exception:
Uncaught PHP Exception LogicException: "Cannot set session ID after the session has started."
I'm using Symfony 2.6.4. I can't find any usefull information about this error message. The test worked perfectly a while ago.
class ControllerTest extends WebTestCase
{
public $client = null;
public $route = 'home/';
/**
* #var \Doctrine\ORM\EntityManager
*/
public $em;
public function setUp()
{
self::bootKernel();
$this->client = static::createClient();
$this->em = static::$kernel->getContainer()
->get('doctrine')
->getManager()
;
}
public function logIn($role = 'admin')
{
if ($role === 'admin') {
$userId = 20;
} elseif ($role === 'user') {
$userId = 29;
}
$user = $this->em->getRepository('Acme\DemoBundle\Entity\User')->find($userId);
$session = $this->client->getContainer()->get('session');
$firewall = 'main';
$token = new UsernamePasswordToken($user, $user->getPassword(), $firewall);
$session->set('_security_'.$firewall, serialize($token));
$session->save();
$cookie = new Cookie($session->getName(), $session->getId());
$this->client->getCookieJar()->set($cookie);
}
public function getFormData($valid = true)
{
//function to generate (in)valid formdata
}
public function getFormRequest($data, $url)
{
return $this->client->request(
'POST',
$url,
$data,
[],
[
'CONTENT_TYPE' => 'application/json',
'HTTP_X-Requested-With' => 'XMLHttpRequest',
]
);
}
//works OK
public function testNewScenario()
{
$url = $this->baseurl . 'new';
$this->logIn('admin');
$crawler = $this->client->request('GET', $url);
$this->assertEquals(200, $this->client->getResponse()->getStatusCode(), "Unexpected HTTP status code for GET " . $url);
}
public function testValidNewScenario()
{
$this->logIn('admin');
$validData = $this->getFormData(true);
//this function throws the exception
$this->getFormRequest($validData, $this->baseurl);
$this->assertEquals(200, $this->client->getResponse()->getStatusCode(), "Unexpected HTTP status code for POST " . $this->baseurl);
}
}
Here's the relevant part of my config_test.yml:
framework:
test: ~
session:
storage_id: session.storage.mock_file
profiler:
collect: false
What's going on?
I don't know if this is still a problem for the OP as this is an old post, but the same issue had me running around in circles for best part of 3 hours trying to find a way out of it. And seeing as there doesnt seem to be a solution anywhere at all. Heres a possible one.
The problem exists in tests which are trying to create a full login.
Current symfony docs state that its preferred to use basic_http authentication in your tests, but if, like me, you need to be testing access levels youll need to be following this method.
The problem seems to occur when we try to set the cookieJar up. This (for me) always threw an error.
Cannot set session ID after the session has started
the solution as it turns out is reasonably simple. Wrap the cookie set code in a condition that checks for a current session id.
if( !$this->session->getId() ) {
$this->cookie = new Cookie( $this->session->getName(), $this->session->getId() );
$this->client->getCookieJar()->set( $this->cookie ); // <--- this is the problem line
}
its also worth noting that calling $this->session->invalidate() does not solve the issue.
I hope this helps someone and saves them some time.
This effected me on Symfony2.1 (no chance of upgrading), but Ive seen mentions of 2.6 getting it when combined with FOSFacebookBundle (where I believe the issue was fixed).