I have recently installed Ratchet on my laravel installation to enable push services over sockets.
This is what my SocketController class looks like (note: it does NOT extend controller)
class SocketController implements WampServerInterface
{
/**
* A lookup of all the topics clients have subscribed to
*/
protected $subscribedTopics = array();
public function onSubscribe(ConnectionInterface $conn, $topic) {
echo"\n SUBSCRING TOPIC: $topic";
echo " hi \n";
try {
JWTAuth::parseToken("okay");
} catch (TokenExpiredException $e) {
echo "hi" ;
} catch (TokenInvalidException $e) {
echo "hi" ;
} catch (JWTException $e) {
echo "hi" ;
}
catch(\Exception $q){
echo $q;
}
$this->subscribedTopics[$topic->getId()] = $topic;
}
/**
* #param string JSON'ified string we'll receive from ZeroMQ
*/
public function onBlogEntry($entry) {
$entryData = json_decode($entry, true);
// If the lookup topic object isn't set there is no one to publish to
if (!array_key_exists($entryData['category'], $this->subscribedTopics)) {
return;
}
$topic = $this->subscribedTopics[$entryData['category']];
// re-send the data to all the clients subscribed to that category
$topic->broadcast(rand(5,666666));
}
public function onUnSubscribe(ConnectionInterface $conn, $topic) {
}
public function onOpen(ConnectionInterface $conn) {
echo"open";
}
public function onClose(ConnectionInterface $conn) {
echo "close";
}
/* The rest of our methods were as they were, omitted from docs to save space */
/**
* If there is an error with one of the sockets, or somewhere in the application where an Exception is thrown,
* the Exception is sent back down the stack, handled by the Server and bubbled back up the application through this method
* #param ConnectionInterface $conn
* #param \Exception $e
* #throws \Exception
*/
function onError(ConnectionInterface $conn, \Exception $e)
{
// TODO: Implement onError() method.
}
/**
* An RPC call has been received
* #param \Ratchet\ConnectionInterface $conn
* #param string $id The unique ID of the RPC, required to respond to
* #param string|Topic $topic The topic to execute the call against
* #param array $params Call parameters received from the client
*/
function onCall(ConnectionInterface $conn, $id, $topic, array $params)
{
// TODO: Implement onCall() method.
}
/**
* A client is attempting to publish content to a subscribed connections on a URI
* #param \Ratchet\ConnectionInterface $conn
* #param string|Topic $topic The topic the user has attempted to publish to
* #param string $event Payload of the publish
* #param array $exclude A list of session IDs the message should be excluded from (blacklist)
* #param array $eligible A list of session Ids the message should be send to (whitelist)
*/
function onPublish(ConnectionInterface $conn, $topic, $event, array $exclude, array $eligible)
{
// TODO: Implement onPublish() method.
}
I am using the JWT library, and just to check,have the line
JWTAuth::parseToken("okay");
But that line throws an error:
exception 'RuntimeException' with message 'A facade root has not been
set.'
How do I include JWT auth into my own class ?
Related
I am building out an interface to create a self-serve way for people to manage their Cognito IDP, but am struggling to pull through the actual data. I know I've got the foundations here but there's something I'm missing. I really need a little direction to help me get back on track.
Where it's failing is in the onPreSetData but I feel like I'm not 100% on all of the code, it's passing null through within the onPreSetData in my loginSettingsType on:
$cognitoAPIFacade = new CognitoAPIFacade();
To try work around this I was hard coding the variables but not going too well haha
it takes a bit of following but I'm certain I'm 99% there and just need a little help to get fully over the line
I'm not the most experienced coder so this is all new learning for me, any help you can provide is hugely appreciated.
I've tried adding comments to the code where it felt good to, I can clarify any areas as needed
My controller is below:
public function editAction(string $customerId, Admin $user, Request $request): Response
{
$customer = $this->validateCustomer($customerId, $user);
$twoFactorOmniLoginFacade = new TwoFactorOmniLoginFacade();
$cognitoAPIFacade = new CognitoAPIFacade();
$cognitoCustomerUserpoolIDP = new CognitoCustomerUserPool();
$formData = new LoginSettingsFormData($customer, $twoFactorOmniLoginFacade, $cognitoAPIFacade, $cognitoCustomerUserpoolIDP);
$form = $this->createForm(LoginSettingsType::class, $formData);
$form->handleRequest($request);
return $this->render('customer/login_settings.twig', [
'title' => $customer->getName(),
'javascript_action' => $request->attributes->get('_route'),
'form' => $form->createView(),
'page' => 'customer_login_settings',
] + $this->getTemplateParams($user, $customer));
}
/**
* #Route("", name="customer_login_settings_put", methods={"PUT"})
*
* #param Request $request
* #param Admin $user
* #param string $customerId
*
* #return Response
*
* #throws Exception
*/
public function putAction(Request $request, Admin $user, string $customerId): Response
{
$customer = $this->validateCustomer($customerId, $user);
$customerCognitoSettingsRepo = $this->getManager()->getRepository(CognitoCustomerUserPool::class);
$userPool = $customerCognitoSettingsRepo->getByCustomerID($customer->getCustomerUuid());
$twoFactorOmniLoginFacade = new TwoFactorOmniLoginFacade();
$cognitoAPIFacade = new CognitoAPIFacade();
$cognitoCustomerUserpoolIDP = new CognitoCustomerUserPool();
$formData = new LoginSettingsFormData($customer, $twoFactorOmniLoginFacade, $cognitoAPIFacade, $cognitoCustomerUserpoolIDP);
$form = $this->createForm(LoginSettingsType::class, $formData);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$formData->saveChanges($customer);
$this->addFlash('success', 'Changes saved successfully');
} else {
$this->addFlash('error', 'There was an error saving changes');
}
return $this->redirectToRoute('customer_login_settings_edit', ['customer_id' => $customerId]);
}
Login settings type:
public function buildForm(FormBuilderInterface $builder, array $options) {
---
form $builder adds
---
$builder->addEventListener(FormEvents::PRE_SET_DATA, [$this, 'onPreSetData']);
}
public function onPreSetData(FormEvent $event, LoggerInterface $logger): void
{
$twoFactorOmniLoginFacade = new TwoFactorOmniLoginFacade();
// Both of these below are returning empty when I use VSCode breakpoints
$cognitoAPIFacade = new CognitoAPIFacade();
$cognitoCustomerUserpoolIDP = new CognitoCustomerUserPool();
$formData = $event->getData();
$form = $event->getForm();
// TODO: I was working on this but unsure where to go from here
// $cognitoCustomerUserpoolIDP = $formData->getCognitoCustomerUserpoolIDP();
if (!$formData) {
return;
}
$idpsettings = $cognitoAPIFacade->getCognitoIDPSettings($logger, $cognitoCustomerUserpoolIDP);
$customer = $formData->getCustomer();
$form = $this->createForm(LoginSettingsType::class, $formData)
---
$Builder adds
---
}
Key script from Facade I made:
public function getCognitoIDPSettings(LoggerInterface $logger, string $cognitoCustomerUserpoolIDP): array
{
$body = json_encode([
'cognito_customer_user_pool_idp_id' => $cognitoCustomerUserpoolIDP,
]);
$url = COGNITO_API_INVOKE_URL . '/idp/get';
$response = $this->postFunction($logger, $url, $body, 'application/json');
$this->checkResponseStatus($response);
$body = json_decode($response->getContent(), true);
if (JSON_ERROR_NONE !== json_last_error()) {
throw new JsonException("failed decoding response from cognito api");
}
return $body;
}
I separated out my form data as it was quite large:
class LoginSettingsFormData
{
private $customer;
private $twoFactorOmniLoginFacade;
private $cognitoAPIFacade;
private $cognitoCustomerUserpoolIDP;
private $ignoreUsageDeactivate;
private $twoFactorLoginApplication;
private $whitelistedIps = [];
/**
* Constructor for the class.
*
* #param CustomerEntity $customer Customer Entity object
* #param TwoFactorOmniLoginFacade $twoFactorOmniLoginFacade Two-factor omni login facade object
* #param CognitoAPIFacade $cognitoAPIFacade Cognito API facade object
* #param CognitoCustomerUserPool $cognitoCustomerUserpoolIDP Cognito customer user pool object
*/
public function __construct(
CustomerEntity $customer,
TwoFactorOmniLoginFacade $twoFactorOmniLoginFacade,
CognitoAPIFacade $cognitoAPIFacade,
CognitoCustomerUserPool $cognitoCustomerUserpoolIDP)
{
$this->customer = $customer;
$this->twoFactorOmniLoginFacade = $twoFactorOmniLoginFacade;
$this->cognitoAPIFacade = $cognitoAPIFacade;
$this->cognitoCustomerUserpoolIDP = $cognitoCustomerUserpoolIDP;
$this->ignoreUsageDeactivate = $customer->getLoginSettings()->isIgnoreUsageDeactivate();
$this->twoFactorLoginApplication = CustomerSetting::findByCustomerUuid($customer->getId())->twoFactorLoginApplication;
$this->whitelistedIps = $customer->getLoginWhitelist();
}
/**
* Submit changes made to the loggin settings
*
* #param array $formData Array of form data
* #param LoggerInterface $logger Logger to log errors
*/
public function submit(array $formData, LoggerInterface $logger)
{
// Check if idp is set
if (null !== $this->idp && 'none' === $formData['idp_type']) {
// Delete the Cognito IDP settings with the provided logger and idp
$this->cognitoAPIFacade->deleteCognitoIDPSettings($logger, $this->idp);
// exit early
return;
}
if ('none' !== $formData['idp_type']) {
// Create a user pool with the provided form data and logger
// TODO:: consider handle exceptions?
$this->cognitoAPIFacade->createUserPool($logger, $formData);
}
}
/**
* Update the identity provider for the loggin settings
*
* #param CognitoAPIFacade $cognitoAPIFacade
* #param CognitoAPIFacade $userpool
* #param Logger $logger Logger to log errors
*/
public function updateIdentityProvider(CognitoAPIFacade $cognitoAPIFacade, $userpool, Logger $logger): void
{
// Assign the user pool value from the cognitoAPIFacade
$userPool = $cognitoAPIFacade->getUserPool();
// log error message if the user pool is null
if (null === $userPool) {
$logger->error("User pool is null, please check the configuration");
return;
}
// Store provider for quick reference
$idp = $userPool->getIdentityProvider();
// If the selected identityprovider is null
if (null === $idp) {
// Check if the form data specifies to set the identityprovider to "none"
if ($this->idpType !== 'none' && $this->active) {
// Otherwise, create a new identityprovider using the form data
$cognitoAPIFacade->createUserPool($logger, $this);
}
return;
}
// Check if the form data specifies to set the identityprovider to "none"
if ($this->idpType === 'none') {
// If so, delete the existing identityprovider settings
$cognitoAPIFacade->deleteCognitoIDPSettings($logger, $idp);
return;
}
// If the form data specifies a different identity provider than the current one
if ($idp->getCognitoIDPSettings() !== $this->idpType
&& ($this->idpType === "SAML" || $this->idpType === "Google")
&& $idp->getCognitoIDPSettings() === "none") {
// Delete the existing identityprovider settings and create a new user pool using the form data
$cognitoAPIFacade->deleteCognitoIDPSettings($logger, $idp);
$cognitoAPIFacade->createUserPool($logger, $this);
}
}
/**
* Save changes made to the object to the database
*
* #return bool Returns true if the changes were saved successfully, false otherwise
*/
public function saveChanges(CustomerEntity $customer)
{
// Set the ignore usage deactivate flag in the customer's login settings
$this->customer->getLoginSettings()->setIgnoreUsageDeactivate($this->ignoreUsageDeactivate);
// Clear the current whitelist of IP addresses for the customer's login settings
$this->customer->getLoginWhitelist()->clear();
// Add each IP address to the whitelist in the customer's login settings
foreach ($this->whitelistedIps as $ip) {
$this->customer->getLoginWhitelist()->add($ip);
}
// Save the changes to the customer object
$this->customer->save();
}
/**
* Set whether to ignore usage deactivation
*
* #param bool $ignoreUsageDeactivate true to ignore usage deactivation, false otherwise
*/
public function setIgnoreUsageDeactivate(bool $ignoreUsageDeactivate)
{
$this->ignoreUsageDeactivate = $ignoreUsageDeactivate;
}
/**
* Bool check whether usage deactivation is ignored
*
* #return bool true if usage deactivation is ignored, false otherwise
*/
public function isIgnoreUsageDeactivate(): bool
{
return $this->ignoreUsageDeactivate;
}
/**
* Set the two factor login application
*
* #param mixed $twoFactorLoginApplication the two factor login application
*/
public function setTwoFactorLoginApplication($twoFactorLoginApplication)
{
$this->twoFactorLoginApplication = $twoFactorLoginApplication;
}
/**
* Get the two factor login application
*
* #return mixed the two factor login application
*/
public function getTwoFactorLoginApplication()
{
return $this->twoFactorLoginApplication;
}
/**
* Set the customer entity
*
* #param CustomerEntity $customer the customer entity
*/
public function setCustomer(CustomerEntity $customer)
{
$this->customer = $customer;
}
/**
* Get the customer entity
*
* #return CustomerEntity the customer entity
*/
public function getCustomer(): CustomerEntity
{
return $this->customer;
}
/**
* Set the whitelisted IP addresses
*
* #param array $whitelistedIps the array of whitelisted IP addresses
*/
public function setWhitelistedIps(array $whitelistedIps)
{
$this->whitelistedIps = $whitelistedIps;
}
/**
* Get the array of whitelisted IP addresses
*
* #return array the array of whitelisted IP addresses
*/
public function getWhitelistedIps(): array
{
return $this->whitelistedIps;
}
/**
* Get the two factor applications
*
* #return mixed the two factor applications
*/
public function getTwoFactorApplications()
{
return $this->twoFactorOmniLoginFacade->findTwoFactorApplications($this->customer);
}
/**
* Get the two factor login setting
*
* #return mixed the two factor login setting
*/
public function getTwoFactorLoginSetting()
{
return $this->twoFactorOmniLoginFacade->findTwoFactorLoginSetting($this->customer->getId());
}
/**
* Get the Cognito IDP settings
*
* #return mixed the Cognito IDP settings
*/
public function getCognitoIDPSettings()
{
return $this->cognitoAPIFacade->getCognitoIDPSettings($this->cognitoCustomerUserpoolIDP);
}
src/Controller/DataTableController.php
<?php
use DataTables\DataTablesInterface;
/**
* Symfony 3.4 and above
*
* #Route("/users", name="users")
*
* #param Request $request
* #param DataTablesInterface $datatables
* #return JsonResponse
*/
public function usersAction(Request $request, DataTablesInterface $datatables): JsonResponse
{
try {
// Tell the DataTables service to process the request,
// specifying ID of the required handler.
$results = $datatables->handle($request, 'users');
return $this->json($results);
}
catch (HttpException $e) {
// In fact the line below returns 400 HTTP status code.
// The message contains the error description.
return $this->json($e->getMessage(), $e->getStatusCode());
}
}
/**
* Symfony 3.3 and below
*
* #Route("/users", name="users")
*
* #param Request $request
* #return JsonResponse
*/
public function usersAction(Request $request): JsonResponse
{
try {
/** #var \DataTables\DataTablesInterface $datatables */
$datatables = $this->get('datatables');
// Tell the DataTables service to process the request,
// specifying ID of the required handler.
$results = $datatables->handle($request, 'users');
return $this->json($results);
}
catch (HttpException $e) {
// In fact the line below returns 400 HTTP status code.
// The message contains the error description.
return $this->json($e->getMessage(), $e->getStatusCode());
}
}
I get the error message:
The structure for a class, (not related to Symfony) is
class MyClassController() {
public function myMethodAction() {
}
}
There is not way to avoid a parse error because this is just not valid syntax of PHP.
I have an application run with Symfony 3.4 with MySql and I get a error: 'The EntityManager is closed'. My application running two ways:
1 - A Console application thats is called by a sh script every time. This console app make many inserts in a database table.
2 - A HTTP Route that also insert in same table.
When de console app is running in background if i call the http route i get the error 'The EntityManager is closed'. If I stop de backgroud app the http route works. It's as if the two apps console and http use the same instance EntityManager.
My code:
I Create a service called AbstractRepositoryService. All of my services that manage repositories should extend.
<?php
abstract class AbstractRepositoryService
{
/**
*
* #var EntityManagerIntergace - $em
*/
protected $em;
/**
*
* #param EntityManagerInterface $em
*/
public function __construct(EntityManagerInterface $em) {
$this->em = $em;
}
/**
*
*
* #param String
*
* #return #mixed
*
* #throws RuntimeException
*/
public function __call($method, $args) {
$repository = $this->em->getRepository(static::ENTITY);
if (!method_exists($repository, $method)) {
throw new RuntimeException(
sprintf("Method '%s' not found.", $method),
500
);
}
try {
return call_user_func_array(array($repository, $method), $args);
} catch(Exception $e) {
throw new Exception($e->getMessage(), 500);
}
}
}
My UserRepositoryService where the exception is thrown in the flush method
<?php
final class UserRepositoryService extends AbstractRepositoryService
{
/**
*
* #const String
*/
const ENTITY = 'AppBundle\\Entity\\User';
/**
*
* #param User
*/
public function insert(User $user) {
try {
$this->em->persist($user);
$this->em->flush($user);
} catch (Exception $e) {
throw new Exception($e->getMessage(), 500);
}
}
}
And finaly my service declaration:
app.services.user_repository_service:
public: true
class: AppBundle\Services\UserRepositoryService
arguments:
- '#doctrine.orm.entity_manager'
Solved!
I created a method that generate new EntityManager before insert and works now.
protected function createNewEntityManager() {
return $this->em->create(
$this->em->getConnection(),
$this->em->getConfiguration(),
$this->em->getEventManager()
);
}
And in insert:
public function insert(Crawler $crawler) {
try {
$this->createNewEntityManager();
$this->em->persist($crawler);
$this->em->flush($crawler);
$this->em->close();
} catch (Exception $e) {
throw new Exception($e->getMessage(), 500);
}
}
I've written a function like so:
/**
* Send the soap request to complemar
* #method SendSoapRequest
* #param string $method The requst action
* #param string $requestData The xml
* #access private
*/
private function SOAPRequest( $method, $requestData ){
/** Run the soap request */
$result = $this->SOAPClient->call( $method, $requestData, 'xsi' );
/** Now check if there are errors or faults */
if( $this->SOAPClient->fault ){
/** Save the fault to the last fault message */
$this->SOAPLastFault = print_r( $result, true );
/** Output the error */
echo '<h2>Fault</h2><pre>'.$this->SOAPLastFault.'</pre>';
/** Return false */
return false;
} else {
/** Check soap for erros */
$this->SOAPErrors = $this->SOAPClient->getError();
/** Check soaps return for a message */
if( $this->SOAPErrors ){
/** we have an error output it */
echo '<h2>Error</h2><pre>' . $error . '</pre>';
/** return false */
return false;
}
}
/** No errors return the result */
return $result;
}
I'm trying to send the soap request thats already built above, take the request back in another file and set it in the db. I'm confused on what I should try.
The file I want to write the send and return is below.
class ComplemarUpdateOrderStatus extends \Framework\Event\Cronjob
{
protected static $prefix = "[ComplemarUpdateOrderStatus]: ";
public static function run( data ){
/** Log that we started */
self::logMessage("Started!");
}
{
}
Should I SoapClient::__doRequest???
Any help would be appreciated. I'm very confused.
Just started using ratchet. When I firstly tested it, it worked fine with websockets, got requests etc. But now I am doing the same as I did, but the request (onOpen) isn't even getting requested, and I am getting this JS error:
WebSocket connection to 'ws://localhost:8080/' failed: Error during WebSocket handshake: Unexpected response code: 404
jscode:
var conn = new WebSocket("ws://localhost:8080");
conn.onopen = function(e) {
console.log("Connected!");
conn.send("hello server");
};
conn.onmessage = function (e) {
console.log(e.data);
};
And my source code:
Main file:
require __DIR__ . "../../library/loader.php";
require __DIR__ . "../../vendor/autoload.php";
error_reporting(E_ALL);
use Ratchet\WebSocket\WsServer,
Ratchet\Http\HttpServer,
Ratchet\Server\IoServer;
use bin\library\AsynChatServer;
$server = IoServer::factory(
new HttpServer(
new WsServer(
new AsynChatServer()
)), 8080);
$server->run();
And the server class:
namespace bin\library;
use Ratchet\MessageComponentInterface,
Ratchet\ConnectionInterface,
Ratchet\Server\IoConnection;
use bin\library\database\Db;
use bin\library\model\Client,
bin\library\model\PacketManager;
class AsynChatServer implements MessageComponentInterface {
private $clients;
/** #var Db */
private $database;
/** #var PacketManager */
private $packets;
function __construct()
{
$this->clients = array();
$this->database = new Db();
$this->packets = new PacketManager($this);
AsynChatServer::println("Server has started up.");
}
/**
* When a new connection is opened it will be passed to this method
* #param ConnectionInterface $conn The socket/connection that just connected to your application
* #throws \Exception
*/
function onOpen(ConnectionInterface $conn)
{
echo "request";
/** #var $client Client */
$client = new Client($conn);
$this->clients[$conn->resourceId] = $client;
AsynChatServer::println("New client accepted: " + $client->getClient()->getRemoteAddress());
}
/**
* This is called before or after a socket is closed (depends on how it's closed). SendMessage to $conn will not result in an error if it has already been closed.
* #param ConnectionInterface $conn The socket/connection that is closing/closed
* #throws \Exception
*/
function onClose(ConnectionInterface $conn)
{
// TODO: Implement onClose() method.
}
/**
* If there is an error with one of the sockets, or somewhere in the application where an Exception is thrown,
* the Exception is sent back down the stack, handled by the Server and bubbled back up the application through this method
* #param ConnectionInterface $conn
* #param \Exception $e
* #throws \Exception
*/
function onError(ConnectionInterface $conn, \Exception $e)
{
// TODO: Implement onError() method.
}
/**
* Triggered when a client sends data through the socket
* #param \Ratchet\ConnectionInterface $from The socket/connection that sent the message to your application
* #param string $msg The message received
* #throws \Exception
*/
function onMessage(ConnectionInterface $from, $msg)
{
/** #var $client Client */
$client = $this->clients[$from->resourceId];
AsynChatServer::println("Paccket received from: " . $client->getClient()->getRemoteAddress());
$this->packets->processPacket($client, $msg);
}
public static function println($message) {
echo $message . "\n";
}
public function getDB() {
return $this->database;
}
}
Is there something wrong? Could the library be corrupted so I need to re-set it up?
This is the output i get when I run:
c:\xampp1\php>php c:/xampp1/htdocs/AsynChat/bin/AsynChat.php
Server has started up.
Nothing else when I connect, no signle error.
What is wrong?
NETSTAT -A:
TCP 127.0.0.1:8080 Ben-╧╩:0 LISTENING
TCP 127.0.0.1:8080 Ben-╧╩:0 LISTENING
My App.php constructor:
public function __construct($httpHost = 'localhost', $port = 8080, $address = '127.0.0.1', LoopInterface $loop = null) {