voryx / ThruwayBundle

Bundle for building Real-time Apps in Symfony
98 stars 47 forks source link

Push message to specific user #41

Closed NewOldMax closed 8 years ago

NewOldMax commented 8 years ago

Hi!

I'm trying to implement notifications in my project. My use case: User 1 creates Task 1 and subscribes to "tasks" channel. User 2 edits Task 1 and subscribes to "tasks" channel. User 1 must receive notification about task edit, and User 2 should not receive this notification.

I see in docs:

$client = $this->container->get('thruway.client');
$client->publish("com.myapp.hello_pubsub", [$value]);

But as I understand, this code publishes message to all subscribed users.

Is there a way to push message for specific User, and not for all?

davidwdan commented 8 years ago

You can use the _thruway_eligible_authids option:

$client->publish("com.myapp.hello_pubsub", [$value], null, ["_thruway_eligible_authids"=>[$authid]]);

You can also publish to specific roles with the _thruway_eligible_authroles option.

NewOldMax commented 8 years ago

Hi, @davidwdan

Thanks for answer. I tried your solution, but messages still published to all connected users, not for specific authid.

NewOldMax commented 8 years ago

My client setup (ReactJS)

        AutobahnReact.Connection.makeConnection({
            url: 'ws://10.128.1.111:8080/ws',
            realm: 'realm1',
            authmethods: ["wampcra"],
            authid: localStorage.getItem('jwt'),
        });
        let connection = AutobahnReact.Connection.reconnectWithAuth(localStorage.getItem('jwt'), '');
        connection.then((session, details) => {
            console.log("Hey, connection established!");
            session[0].subscribe('app.tasks', (msg) => {
                console.log(msg);
            })
        }).catch((details) => {
          console.log("Hey, connection lost! " + details);
        })

And I tried

        $client = $this->getContainer()->get('thruway.client');
        $authid = 'my_custom_jwt';
        $client->publish('app.tasks', ['test'], null, ['_thruway_eligible_authids' => [$authid]]);
stingus commented 8 years ago

Use a separate channel for each user, for example "com.myapp.hello_pubsub.12345", where 12345 is the user id. Don't forget to use the authorization manager to check the permissions to subscribe to individual channels. I have a similar notification system in place and it works really well.

mbonneau commented 8 years ago

I have tested the following using the WampCRA router in the Examples folder and found it to properly publish to only selected authids:

<?php

use Thruway\Authentication\ClientWampCraAuthenticator;
use Thruway\ClientSession;
use Thruway\Peer\Client;
use Thruway\Transport\PawlTransportProvider;

require_once __DIR__ . '/vendor/autoload.php';

$client = new Client('realm1');

$client->addTransportProvider(new PawlTransportProvider('ws://127.0.0.1:9090/ws'));
$client->setAuthId('peter');
$client->addClientAuthenticator(new ClientWampCraAuthenticator('peter', 'secret1'));

$client->on('open', function (ClientSession $session) {
    $session->publish('some.topic', ['Hello everyone']);
    $session->publish(
        'some.topic',
        ['Joe should not see this'],
        null,
        ['_thruway_eligible_authids' => ['peter']]
    );
    $session->publish(
        'some.topic',
        ['This is for joe only'],
        null,
        ['_thruway_eligible_authids' => ['joe']]
    );
});

$client->start();

I then added this to WampCraLogin.html:

session.subscribe('some.topic', function (args) {
    console.log(args);
});

Please note that this feature with be updated to match the current spec (eligible_authid) in the future. (we will deprecate the _thruway_eligible_authids for the next version prior to removable)

NewOldMax commented 8 years ago

It strange, but your example the same sends message to all users (not only for 'peter') :(

Can you share full code of your example?

it does not matter, I found

NewOldMax commented 8 years ago

@stingus , in you solution, how you defined subscribe routes? I think i can't use something like

   /**
     * @Subscribe("com.tasks.{userid}")
     */

i get wamp.error.invalid_uri error

UPDATE: I figured out, standard annotations works well (@Subscribe("com.tasks")) and handles com.tasks.userid subscriptions. But in my case, I have user id like 25c722aa-58c8-477c-ac4d-17420137ded8 and uriIsValid function stuck with - symbol. Can you add - char to regex? It will solve my problems as well.

NewOldMax commented 8 years ago

@davidwdan , @mbonneau , please, look at last update, if you have time.

davidwdan commented 8 years ago

@NewOldMax What version of Thruway are you using?

Adding a - to the regex will violate WAMP's strict URI conventions, which is what Thruway uses.

NewOldMax commented 8 years ago

I'm not specify version of Thruway, only install ThruwayBundle. In composer.lock Thruway version is 0.3.1

If there is a way to override regex for my use case? Or only use fork?

davidwdan commented 8 years ago

The ability to publish to specific users was added in 0.3.4. You should upgrade Thruway to at least that version.

NewOldMax commented 8 years ago

Successfully upgraded to 0.3.10 and all issues gone. You can close this issue now. Thanks!