cdr95985

cdr95985

Member Since 1 Year Ago

Experience Points
660
Total
Experience

4,340 experience to go until the next level!

In case you were wondering, you earn Laracasts experience when you:

  • Complete a lesson — 100pts
  • Create a forum thread — 50pts
  • Reply to a thread — 10pts
  • Leave a reply that is liked — 50pts
  • Receive a "Best Reply" award — 500pts
Lessons Completed
4
Lessons
Completed
Best Reply Awards
0
Best Reply
Awards
  • start-engines Created with Sketch.

    Start Your Engines

    Earned once you have completed your first Laracasts lesson.

  • first-thousand Created with Sketch.

    First Thousand

    Earned once you have earned your first 1000 experience points.

  • 1-year Created with Sketch.

    One Year Member

    Earned when you have been with Laracasts for 1 year.

  • 2-years Created with Sketch.

    Two Year Member

    Earned when you have been with Laracasts for 2 years.

  • 3-years Created with Sketch.

    Three Year Member

    Earned when you have been with Laracasts for 3 years.

  • 4-years Created with Sketch.

    Four Year Member

    Earned when you have been with Laracasts for 4 years.

  • 5-years Created with Sketch.

    Five Year Member

    Earned when you have been with Laracasts for 5 years.

  • school-session Created with Sketch.

    School In Session

    Earned when at least one Laracasts series has been fully completed.

  • welcome-newcomer Created with Sketch.

    Welcome To The Community

    Earned after your first post on the Laracasts forum.

  • full-time-student Created with Sketch.

    Full Time Learner

    Earned once 100 Laracasts lessons have been completed.

  • pay-it-forward Created with Sketch.

    Pay It Forward

    Earned once you receive your first "Best Reply" award on the Laracasts forum.

  • subscriber-token Created with Sketch.

    Subscriber

    Earned if you are a paying Laracasts subscriber.

  • lifer-token Created with Sketch.

    Lifer

    Earned if you have a lifetime subscription to Laracasts.

  • lara-evanghelist Created with Sketch.

    Laracasts Evangelist

    Earned if you share a link to Laracasts on social media. Please email [email protected] with your username and post URL to be awarded this badge.

  • chatty-cathy Created with Sketch.

    Chatty Cathy

    Earned once you have achieved 500 forum replies.

  • lara-veteran Created with Sketch.

    Laracasts Veteran

    Earned once your experience points passes 100,000.

  • 10k-strong Created with Sketch.

    Ten Thousand Strong

    Earned once your experience points hits 10,000.

  • lara-master Created with Sketch.

    Laracasts Master

    Earned once 1000 Laracasts lessons have been completed.

  • laracasts-tutor Created with Sketch.

    Laracasts Tutor

    Earned once your "Best Reply" award count is 100 or more.

  • laracasts-sensei Created with Sketch.

    Laracasts Sensei

    Earned once your experience points passes 1 million.

  • top-50 Created with Sketch.

    Top 50

    Earned once your experience points ranks in the top 50 of all Laracasts users.

Level 1
660 XP
Jan
30
1 year ago
Activity icon

Replied to Authorizing Private Event Channels (not Triggering WebSocket Server Listener). Public Events Work! - Laravel 5.5

@tiagomatosweb when I posted this question, I was using my own Socket.io implementation. I have since moved on to use the laravel-echo-server (community server), specifically to address the channel authentication problem.

From what I read in the source code of laravel echo (included in laravel js dependencies)--which I will refer to as Echo from here on out--and the laravel-echo-server... it appears that when Echo is instantiated on the client side, and if you are "subscribing" it to a channel that needs to be authenticated as defined in the laravel docs ( i.e. Echo.private() .notify()... NOT .public() ), Echo will try to hit an authentication route which is based on how you configure Echo in /resources/assets/js/app.js or bootstrap.js.

Since I was using my own socket.io implementation, it did not hit the auth url on the socket.io server I had (because it didn't exist) so it never authenticated the user. I think it is by design that Echo will return "true" and allow a user to listen to a private or notify channe if the auth url returns a 404... again, the code that triggers the auth in Echo is under the hood. You can find it yourself on github if youre curious.

The laravel echo server actually has an endpoint for authenticating private / notify channels. It accepts a csrf token and some more details needed to auth a user from Echo, builds a request, and sends it to the auth route in the laravel php application (which is a default route provided from laravel 's broadcast auth routes I think). The echo server will then respond with the laravel app's indication of whether or not a user is authorized based on what it was sent.

So, tl;dr: implement a laravel echo server.

Oh, to save you another headache.. If you are developing on the same server you will be hosting your production environment on, prefix your channels that you broadcast on with the app's environment. You will also need to prefix the channels on the client side with the same variable. I did this by passing the environment down when rendering the layout file in blade.

Laravel echo server does not support multiple instances out of the box. That is how I get around that implementation. So you will likely have one redis server and one laravel echo server on your stack.

Let me know if you have other issues. Thanks =)

P.S. I'm on my phone, sorry for typos

Nov
07
1 year ago
Activity icon

Started a new conversation Laravel Echo Does Not POST To /broadcasting/auth On Page Load

I am using Laravel 5.5. When landing on a page that includes the Laravel app.js compiled typescript with Laravel Echo instantiated, as well as Echo listening to a private channel, I noticed that the /broadcasting/auth endpoint is not being called.

I am using the socket.io provider with a custom socket.io server. I have public, private, and presence events broadcasting to the client, however, the private and presence requests are not being authenticated--they are instead being treated like public events.

Does anyone have any idea why this is?

Nov
06
1 year ago
Activity icon

Started a new conversation Private And Presence Events Work But Do Not Get Ran Through Broadcasting Authorization?

I have events broadcasting over the public, private, and presence channels, however, the private and presence events are NOT getting authorized. Even though they are NOT getting run through the broadcasting authorization middleware... regardless, the events are still being emitted to the clients.

I am using Laravel 5.5 with a custom socket.io websocket server with Redis. I am also using Laravel Echo and Vue on the client side. Again, all 3 event types are broadcasting to all clients appropriately. I just want the channels to be authorized!

Below is the relevant code.

TestController.php

    public function firePrivateEvent()
    {
        $data = [
            'username' => 'Private JohnDoe'
        ];
        
        broadcast(new \App\Events\PrivateEvent($data));
        return "TRUE";
    }

PrivateEvent.php

namespace App\Events;

use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Support\Facades\Log;

class PrivateEvent implements ShouldBroadcast
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    public $data;
            
    /**
     * Create a new event instance.
     *
     * Data passed in will be serialized, along with any public properties
     * 
     * @return void
     */
    public function __construct($data)
    {
        //
        $this->data = $data;
        
    }

    /**
     * Get the channels the event should broadcast on.
     *
     * @return \Illuminate\Broadcasting\Channel|array
     */
    public function broadcastOn()
    {
        //return new PrivateChannel('test-channel');
        Log::Info("[Event Raised]: PrivateEvent on private-channel");
        return new PrivateChannel('private-channel');
    }
}

BroadcastServiceProvider.php

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Broadcast;

class BroadcastServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        Broadcast::routes();

        require base_path('routes/channels.php');
    }
}

Channels.php

Broadcast::channel('private-channel', function($user) {
    Log::Info("Authorizing private-channel event"); // this is never logged!
    return true;
});

Socket.io server: app.js

redis.subscribe('private-private-channel'); // I've instantiated PrivateChannel with a channel name of 'private-channel', therefore the channel I want to subcribe to is 'private-private-channel', since that class prepends 'private-' to the value passed in.

redis.on('message', function(channel, message){
   
    message = JSON.parse(message);
    console.log('-------------------')
    console.log("MSG FIRED");
    console.log('message channel: ' + channel);
    console.log('message event: ' + message.event);
    console.log(message);
    console.log('emit to: ' + channel + ':' + message.event);
    io.emit(message.event, channel, message.data);
    console.log('-------------------')
});

Client side JS. The CRSF Token, compiled app.js typescript, and the socket.io library are included in the page as well.

            var pr = Echo.private('private-channel')
            .listen('PrivateEvent', (e) => {
                console.log("[GOT PRIVATE EVENT]:");
                console.log(e);
                this.users.push(e);
            });

Please let me know if you have any suggestions. Thank you!

P.S. I created an axios POST request to domain.com/broadcasting/auth with the following channel defined at the END of channels.php. I am able to get the $user object back on the client side when using this request.

However, neither my private nor presence events/channels are getting picked up by this code (they go through as if they're public events)

Broadcast::channel('{t}', function ($user) {
    //return (int) $user->id === (int) $id;
    return $user;
});

Nov
03
1 year ago
Activity icon

Replied to Authorizing Private Event Channels (not Triggering WebSocket Server Listener). Public Events Work! - Laravel 5.5

*** Channel Authorization Problem ***

While this is all wonderful, it appears that my broadcasting routes / channels are NOT being checked against the authorization method I defined in channels.php.

Broadcast::channel('private-private-channel', function($user) {
    Log::Info("Authorizing private-private-channel event");
    return 0;
});

Broadcast::channel('private-channel', function($user) {
    Log::Info("Authorizing private-channel event");
    return 0;
});

I would assume I would HAVE to manually define the private channels with the "private-" prefix. Either way, neither log messages are being fired. Any advice as to how and why?

Note: The Echo.private() channel subscription has the following options under auth:

authEndpoint: "/broadcasting/auth"
broadcaster: "socket.io"
csrfToken: null
host: "https://mydomain.com:3031"
hostname: "dev.mydomain.com"

My concern is that Echo is trying to authorize to "dev.mydomain.com:3031/broadcasting/auth", but that is where the socket.io server is being hosted. I am assuming that Echo is smart enough to hit the Laravel App at the hostname, and not the host, but who knows? Any advice? Thanks!

Activity icon

Replied to Authorizing Private Event Channels (not Triggering WebSocket Server Listener). Public Events Work! - Laravel 5.5

Update: I was able to get the private events to broadcast and to be picked up by the socket.io server, as well as emitting them to the client side. However, it appears that the requests aren't being checked against my authorization code defined in channels.php.

First I'll talk about how I got the private broadcasts to work, then I'll talk about the lack of authorization over the private channels.

How I get the private broadcasts to work

TL;DR

It appears that when defining an event to broadcast on a private channel, Laravel takes the $channelName that you pass in and APPENDS it with 'private-'.

On your socket.io server, you should subscribe to "private-$channelName".

On your client side javascript, using Echo, you should subscribe to a private channel like so: Echo.private($channelName).Listen(...).

END TL;DR

It appears that, when using Laravel-Echo and subscribing to a private channel like so:

            var pr = Echo.private('private-channel')
             .listen('PrivateEvent', (e) => {
                 console.log("[GOT PRIVATE EVENT]:");
                 console.log(e);
             });

... will actually APPEND A PREFIX to the channel name that we pass in. So, when I logged "pr" to the console, I found that the channel name that it was LISTENING to was 'private-private-channel'.

SocketIoPrivateChannel {events: {…}, name: "private-private-channel", socket: r, options: {…}, eventFormatter: EventFormatter}
eventFormatter
:
EventFormatter {namespace: "App.Events"}
.
.
.

I thought "hm, weird", so I wondered if Laravel itself did the same thing when it broadcasts on private channels using event(new App\Event\SomeEventThatBroadcastsOnPrivateChannel), where the broadcastOn() function looks like so:

    public function broadcastOn()
    {
        //return new PrivateChannel('test-channel');
        Log::Info("[Event Raised]: PrivateEvent on private-channel");
        return new PrivateChannel('private-channel');
    }

In the socket.io server, I subscribed to 'private-private-channel', and sure enough, the redis.on('message') event was fired, and my Echo client code picked up the emitted data (while I instantiated it with 'private-channel', it listened for 'private-private-channel')!

Activity icon

Replied to Change Log Name In Laravel 5.5

@Talinon, That did it. Thank you so much for your time! I was unaware of the setfacl command--this could be very useful in the future. Thanks a lot!

Oct
31
1 year ago
Activity icon

Started a new conversation Authorizing Private Event Channels (not Triggering WebSocket Server Listener). Public Events Work! - Laravel 5.5

I have implemented a Socket.IO Server with my Laravel 5.5 Application. I am able to broadcast and update the view to all connected clients using public events. However, when I try using private events, it seems that these are not triggering the listener on my socket.io server.

What is happening now from and end-user standpoint: When a user connects to the page, the web socket server log knows that a user connected. When firing the event (which occurs when the user hits the page), the event is logged in laravel.log. The event is sent to the queue and in Redis (I can see it in "queues:default" in the Redis db). The Queue Listener is running (manually) and then processes the private event (removing it from the Redis db). The web socket server never catches the broadcasted event over the "private-channel" at this point.

NOTE: The authorization route for "private-channel" NEVER fires off the log as defined!

I've verified that the channel name is spelled correctly in the web socket server, the event class, and the client page.

Below is the relevant code (I think).

TestController.php @ app.com/PrivateEvent


    public function firePrivateEvent()
    {
        $data = [
            'username' => 'Private JonDoe'
        ];
        
        // This is firing but not getting caught by socket.io
        event(new \App\Events\PrivateEvent($data));
        return view('test.redis');
    }

PrivateEvent.php

The log message in here is getting fired.


namespace App\Events;

use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Support\Facades\Log;

class PrivateEvent implements ShouldBroadcast
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    public $data;
            
    /**
     * Create a new event instance.
     *
     * Data passed in will be serialized, along with any public properties
     * 
     * @return void
     */
    public function __construct($data)
    {
        //
        $this->data = $data;
        
    }

    /**
     * Get the channels the event should broadcast on.
     *
     * @return \Illuminate\Broadcasting\Channel|array
     */
    public function broadcastOn()
    {
        //return new PrivateChannel('test-channel');
        Log::Info("[Event Raised]: PrivateEvent on private-channel");
        return new PrivateChannel('private-channel');
    }
}

channels.php

This log message is never recorded.


Broadcast::channel('private-channel', function($user) {
    Log::Info("Authorizing private-channel event");
    return 0;
});

BroadcastingServiceProvider.php


namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Broadcast;

class BroadcastServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        Broadcast::routes();

        require base_path('routes/channels.php');
    }
}

websocketserver.js

The logs here are not getting fired when broadcasting across the private-channel, but they do when broadcasting across the public-channel.


// subscribe to channels in which we want to notify clients on when updated     
redis.subscribe('public-channel');
redis.subscribe('private-channel');

redis.on('message', function(channel, message){
    //console.log(channel, message);
    
    message = JSON.parse(message);
    console.log('-------------------')
    console.log("MSG FIRED");
    console.log('message channel: ' + channel);
    console.log('message event: ' + message.event);
    console.log(message);
    console.log('emit to: ' + channel + ':' + message.event);
//    io.emit(channel + ':' + message.event, message.data); //test-channel:UserSignedUp
      io.emit(message.event, channel, message.data); //test-channel:UserSignedUp
    console.log('-------------------')
});

client_view.blade.php

Obviously we never get this far with the private-channel, but we do with the public-channel. This page has the CSRF token embedded, as well as the client side socket.io library and the compiled typescript "app.js" where Echo is defined in.


    new Vue({
        el: '#users',
        data: {
            users: ["t1", "t2"]
        },
        mounted: function(){
            console.log("Vue is mounted!");
            
            Echo.channel('public-channel')
             .listen('PublicEvent', (e) => {
                 console.log("[GOT PUBLIC EVENT]:");
                 console.log(e);
                 this.users.push(e);
             });
             
            Echo.private('private-channel')
             .listen('PrivateEvent', (e) => {
                 console.log("[GOT PRIVATE EVENT]:");
                 console.log(e);
                 this.users.push(e);
             })
        }
    });

I'm unsure of where to debug next. Can anyone help me? Thanks!

Activity icon

Replied to Change Log Name In Laravel 5.5

@Talinon, your command does bring me one step closer.

This solution fixes the issue with the end-user seeing the file permissions error if the log file was created when the php artisan command was run.

However, my user now receives the file permissions error when running artisan commands after the log was newly created by the end-user hitting the page. This is because the log file is created with read only permissions on the group id.

Only the OWNER of the file can write to the log. The Group only has READ rights. (I am a member of the www-data group, if you were curious). So we need to find a way to either ensure the group can write to the new file when it is created, or find another way to approach this (such as changing the log name, but that appears to be deprecated). Thanks for your time btw.

Activity icon

Replied to Change Log Name In Laravel 5.5

I'm sorry. I should have clarified.

I have my logs set to "daily". When the log file is created on a new day, the file is created with the persmissions "644" or "-rw-r--r--". The owner and group the file belongs to is set to "www-data" (as expected). When hitting the page the log is recorded correctly.

The issue is this:

If the log file does not exist at the time that a "php artisan" command is run, for example, the "php artisan queue:work" or "listen" command, the log file is created with the permissions of the user running the command. After the fact, if an end-user hits a page that writes to the log, the page breaks because it is trying to write to a log that exists but does not belong to www-data.

I hope that is clear. My question is this: how do I prevent this scenario?

P.S. @Talinon, In regards to why I wanted to change the default log name: The thread I linked tries to address the problem by changing the file name to include the server-side username, such that, each user has their own different log. E.g.) create a "logfile-www-data.log" when an end user hits a page, or create a "logfile-root.log" when root runs a php artisan command.

Lastly, the Storage and logs directory has full rights to the www-data group.

Activity icon

Started a new conversation Change Log Name In Laravel 5.5

Hello, how can we change the default log name in Laravel 5.5? I am having issues with logging when running the PHP Artisan Queue:Work and Listen command. The log file that is created is not able to be written to. The owner and group of the created file is www-data.

I saw a solution here: https://laracasts.com/discuss/channels/laravel/log-permission-problem

But that does not apply to Laravel 5.5. Thanks.