Tippin

Tippin

Member Since 5 Months Ago

TAMPA

Experience Points
14,810
Total
Experience

190 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
14
Lessons
Completed
Best Reply Awards
23
Best Reply
Awards
  • start your 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-in-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 Created with Sketch.

    Subscriber

    Earned if you are a paying Laracasts subscriber.

  • lifer Created with Sketch.

    Lifer

    Earned if you have a lifetime subscription to Laracasts.

  • evangelist 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 3
14,810 XP
Aug
03
1 week ago
Activity icon

Replied to API Route Guest Access.

@phpmick One thing you may want to try, set the guard when using guest. Just like auth:api, try guest:api

Route::namespace('\')->middleware('guest:api')->group(function () {
	
});

Jul
26
2 weeks ago
Activity icon

Awarded Best Reply on Where Do I Add Custom.css In Webpack?

@aron-spiess If you want it as it's own file, and not in app.css, you can append another .sass()

mix.js("resources/js/app.js", "public/js/app.js")
    .sass("resources/sass/app.scss", "public/css/app.css")
    .sass("resources/sass/tailwind.scss", "public/css/tailwind.css")
    .sourceMaps();

If you want it included within app.css, then open app.scss and add the import to wherever your tailwind scss file is

@import "tailwind";
Activity icon

Replied to Laravel Broadcasting Private Channel “Client Can Not Be Authenticated, Got HTTP Status 500”

Does your event class implement ShouldBroadcast? Also, do you have a queue worker running? By default, broadcast events are queued. To bypass that, you can implement broadcast now, like so

<?php

namespace App\Events;

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

class Ordered implements ShouldBroadcastNow
{

}
Activity icon

Replied to Laravel Broadcasting Private Channel “Client Can Not Be Authenticated, Got HTTP Status 500”

Does the echo server at least show the event being broadcasted?

Seems your event is called Ordered not OrderedEvent, try:

echo.private('order.8')
    .listen('.Ordered', (e) => {
        console.log("DATA RECEIVED");
        console.log(e);
});

Also, I prefer to give my broadcast events my own name instead of relying on namespaces on the frontend, so try adding broadcast as method into your event class, and edit the name in JS accordingly:

Event class

    public function broadcastAs()
    {
        return 'ordered';
    }

JS

echo.private('order.8')
    .listen('.ordered', (e) => {
        console.log("DATA RECEIVED");
        console.log(e);
});
Activity icon

Replied to Telescope In Production To Record Mail And Jobs?

@moiz Each entry has a type attribute, you can can simply check using their EntryType class, like so:

<?php

namespace App\Providers;

use Illuminate\Support\Facades\Gate;
use Laravel\Telescope\EntryType;
use Laravel\Telescope\IncomingEntry;
use Laravel\Telescope\Telescope;
use Laravel\Telescope\TelescopeApplicationServiceProvider;

class TelescopeServiceProvider extends TelescopeApplicationServiceProvider
{
    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        Telescope::night();

        $this->hideSensitiveRequestDetails();

        Telescope::filter(function (IncomingEntry $entry) {
            if ($this->app->isLocal()) {
                return true;
            }

            return $entry->isReportableException() ||
                   $entry->isFailedRequest() ||
                   $entry->isFailedJob() ||
                   $entry->isScheduledTask() ||
                   $entry->type === EntryType::JOB ||
                   $entry->type === EntryType::MAIL ||
                   $entry->hasMonitoredTag();
        });
    }

https://github.com/laravel/telescope/blob/3.x/src/EntryType.php

Activity icon

Replied to Where Do I Add Custom.css In Webpack?

@aron-spiess If you want it as it's own file, and not in app.css, you can append another .sass()

mix.js("resources/js/app.js", "public/js/app.js")
    .sass("resources/sass/app.scss", "public/css/app.css")
    .sass("resources/sass/tailwind.scss", "public/css/tailwind.css")
    .sourceMaps();

If you want it included within app.css, then open app.scss and add the import to wherever your tailwind scss file is

@import "tailwind";
Activity icon

Replied to Laravel Broadcasting Private Channel “Client Can Not Be Authenticated, Got HTTP Status 500”

First, the second error you got was because you hard coded the ID, but expect a a param still.

Broadcast::channel('order.{id}', function ($user, int $id) {
    return true;
});

Second, when you had type hinted User, did you put the USE at the top of your channels file to point to the correct user model?

use App\Models\Auth\User\User;


Broadcast::channel('order.{id}', function (User $user, int $id) {
    // this is for testing purpose as everyone is authenticated to listen to this channel
    return true;
});

If it still tries to pass the base App\User (may be that gates, policies etc auto inject that model), you may need to look into how to rebind your user model globally

**editing to add, I assume your user model is correct under the providers in config/auth.php?

'providers' => [
    'users' => [
        'driver' => 'eloquent',
        'model' => App\Models\Auth\User::class,
    ],
],
Activity icon

Replied to Laravel Broadcasting Private Channel “Client Can Not Be Authenticated, Got HTTP Status 500”

@evacch When you declare your channel, and you type hint User, is there a reason it is pointing to App\Models\Auth\User\User? Is that your main user model? By default, I think laravel always binds the regular App\User to the channel closure. Try removing the type hint for now and dump what $user it is injecting to find out.

Jul
24
2 weeks ago
Activity icon

Replied to Make Shorter Access Token Laravel Passport

@nithapple They are that long for a reason. It is an encoding of headers, payload and signature. When parsed, your code is:

{
  "aud": "5",
  "jti": "024ace4d06c3b5b0e7e8137d1e5f49b2e66140a6b7cf60686e7409cf918e7d379752f27318a9f4b7",
  "iat": 1595564008,
  "nbf": 1595564008,
  "exp": 1627100008,
  "sub": "1",
  "scopes": []
}

This tells passport what access token ID to compare it to (jti), and other relevant data. Learn more at: https://jwt.io/

Activity icon

Replied to How To Reverse The Notification Class/migration

@webfuelcode If you rename a notification class, you have to restart your worker/queue, as any code changes have to be respawned into the worker memory. Also, a good go to anytime you have class not found issues outside of the queue, is to clear your bootstrap/cache folder and run w.e commands you use for cache (config:cache, routes:cache, etc). Also, check your spelling, usually it is "Notifications" with a capitol, not "notifications" directory.

Jul
23
2 weeks ago
Activity icon

Awarded Best Reply on How Does Passport's "Consuming Your API With JavaScript" Work ?

@cristimocean So when you use the CreateFreshApiToken, behind the scenes, passport put's it into the request as a token, just like the regular Client or Token models, however, it uses the TransientToken model, parading around with full access. If you want to limit what these can do within your API, one thing I have done is create a middleware that simply checks if the token on the request is transient. If it is, I know the request is coming from web, and I can limit it based on that. As for adding scopes, it is a "virtual" token, so that is not directly possible to my knowledge.

https://github.com/laravel/passport/blob/9.x/src/TransientToken.php

As an example, assuming you put this middleware within an auth group, you can try this:

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Laravel\Passport\Token;
use Laravel\Passport\TransientToken;
use Symfony\Component\HttpKernel\Exception\HttpException;

class DenyTransientToken
{
    /**
     * Handle an incoming request.
     *
     * @param  Request  $request
     * @param  Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        /* @var $token Token|TransientToken */

        $token = $request->user()->token();

        if($token && $token->transient())
        {
            throw new HttpException(403, "Unauthorized");
        }

        return $next($request);
    }
}
Jul
22
3 weeks ago
Activity icon

Replied to How Does Passport's "Consuming Your API With JavaScript" Work ?

@cristimocean So when you use the CreateFreshApiToken, behind the scenes, passport put's it into the request as a token, just like the regular Client or Token models, however, it uses the TransientToken model, parading around with full access. If you want to limit what these can do within your API, one thing I have done is create a middleware that simply checks if the token on the request is transient. If it is, I know the request is coming from web, and I can limit it based on that. As for adding scopes, it is a "virtual" token, so that is not directly possible to my knowledge.

https://github.com/laravel/passport/blob/9.x/src/TransientToken.php

As an example, assuming you put this middleware within an auth group, you can try this:

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Laravel\Passport\Token;
use Laravel\Passport\TransientToken;
use Symfony\Component\HttpKernel\Exception\HttpException;

class DenyTransientToken
{
    /**
     * Handle an incoming request.
     *
     * @param  Request  $request
     * @param  Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        /* @var $token Token|TransientToken */

        $token = $request->user()->token();

        if($token && $token->transient())
        {
            throw new HttpException(403, "Unauthorized");
        }

        return $next($request);
    }
}
Activity icon

Replied to POST Method Not Supported Here

If you are using axios, the CSRF token is automatically added to it's headers, assuming you have the default laravel bootstrap.js file. You can also set the CSRF meta attribute in the head section of your html, and in your JS under where axios is imported, you can add:

let token = document.head.querySelector('meta[name="csrf-token"]');
window.Laravel = { csrfToken: token.content };
window.axios = require('axios');
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
Activity icon

Replied to True Or False: Use `\collect()` Over `collect()` - It Is Slightly More Performant.

Personally I never add the preceding slash. My two thoughts on the matter...readability, and all that does is put it in the global namespace, but any of laravel helpers are already connecting and resolving directly to the service container, and helpers are auto loaded by composer. As to the technical side of your question, I have not directly tested "performance" of that.

Activity icon

Replied to POST Method Not Supported Here

Keep in mind resource routes mean the method names themselves are not part of the URL. Rather, /salutations/{salutation} where {salutation} is the ID of the salutation, as laravel can bind the model to the route if you type hint in your controller method. To post delete from a form on the frontend without using javascript, you can add the following to your form:

<form action="/salutations/{{ $salutation->id }}" method="POST">
    @method('DELETE')
</form>

If you are using javascript, such as axios, you can instead call

axios.delete('/salutations/{someID}')

Definitely check out the docs section for resource controllers, they do also list how the URI's are mapped by default https://laravel.com/docs/7.x/controllers#resource-controllers

Activity icon

Awarded Best Reply on POST Method Not Supported Here

@maltekiefer the store method is mapped to posting right to /salutations. Then GET on /salutations/{salutation} would be the show method, etc

Activity icon

Replied to POST Method Not Supported Here

@maltekiefer the store method is mapped to posting right to /salutations. Then GET on /salutations/{salutation} would be the show method, etc

Activity icon

Awarded Best Reply on Accessing BearerToken Details

@dan1234827 Whenever a user is authed on a request using a token, instead of grabbing the bearer token, laravel binds it to the token() on the user for the request. Simply try: $request->user()->token()->revoke() or delete()

class ApiLogout extends Controller
{
    /*
    |--------------------------------------------------------------------------
    | API Logout Controller
    |--------------------------------------------------------------------------
    |
    | This logs out the authenticated user from the api and revokes token
    |
    */

    /**
     * ApiLogout constructor.
     */
    public function __construct()
    {
        $this->middleware('auth:api');
    }

    /**
     * Handle the incoming logout request.
     *
     * @param Request $request
     * @return JsonResponse
     * @throws Exception
     */
    public function __invoke(Request $request)
    {
        /* @var $token Token|TransientToken */

        $token = $request->user()->token();

        if(!$token->transient())
        {
            $token->revoke();
            
            //$token->delete();

            return new JsonResponse([
                'message' => 'Logged out'
            ]);
        }

        throw new HttpException(403, 'Unauthorized to perform that action.');
    }
}
Activity icon

Replied to Accessing BearerToken Details

@dan1234827 Whenever a user is authed on a request using a token, instead of grabbing the bearer token, laravel binds it to the token() on the user for the request. Simply try: $request->user()->token()->revoke() or delete()

class ApiLogout extends Controller
{
    /*
    |--------------------------------------------------------------------------
    | API Logout Controller
    |--------------------------------------------------------------------------
    |
    | This logs out the authenticated user from the api and revokes token
    |
    */

    /**
     * ApiLogout constructor.
     */
    public function __construct()
    {
        $this->middleware('auth:api');
    }

    /**
     * Handle the incoming logout request.
     *
     * @param Request $request
     * @return JsonResponse
     * @throws Exception
     */
    public function __invoke(Request $request)
    {
        /* @var $token Token|TransientToken */

        $token = $request->user()->token();

        if(!$token->transient())
        {
            $token->revoke();
            
            //$token->delete();

            return new JsonResponse([
                'message' => 'Logged out'
            ]);
        }

        throw new HttpException(403, 'Unauthorized to perform that action.');
    }
}
Jul
17
3 weeks ago
Activity icon

Awarded Best Reply on Unable To Listen To Laravel Echo Private Channel

@codebullet I believe it is because your event is being broadcasted with the full namespace. Unless you configure the namespace in laravel echo, I find it easier to add the broadcast as method on the event to rename what it calls itself. Then be sure to prefix the event name you listen for in echo with a ' . ' dot

PrivateChatEvent

public function broadcastAs()
{
    return 'private-chat-event';
}

Vue

        created() {
            Echo.private(`Chat.${this.friend.session.id}`).listen(
                ".private-chat-event",
                (e) => {
                    console.log(e)

                }
            );
Activity icon

Replied to Unable To Listen To Laravel Echo Private Channel

@codebullet I believe it is because your event is being broadcasted with the full namespace. Unless you configure the namespace in laravel echo, I find it easier to add the broadcast as method on the event to rename what it calls itself. Then be sure to prefix the event name you listen for in echo with a ' . ' dot

PrivateChatEvent

public function broadcastAs()
{
    return 'private-chat-event';
}

Vue

        created() {
            Echo.private(`Chat.${this.friend.session.id}`).listen(
                ".private-chat-event",
                (e) => {
                    console.log(e)

                }
            );
Activity icon

Replied to Adding Custom Guard To My RedirectIfAuthenticated Middleware

"Middleware parameters may be specified when defining the route by separating the middleware name and parameters with a :. Multiple parameters should be delimited by commas", thus try guest:business_user, like so -

Route::middleware(['guest:business_user'])->group(function () {
    Route::view('/business/sign-up', 'business.registration')->name('business.registration');
    Route::view('/business/login', 'business.login')->name('business.login');
});
public function handle($request, Closure $next, $guard = null)
{
    if (Auth::guard($guard)->check())
    {
        if($guard === 'business_user')
            return redirect('/business/dashboard');

        return redirect('/dashboard');
    }

    return $next($request);
}

More info here: https://laravel.com/docs/7.x/middleware#middleware-parameters

Jul
14
4 weeks ago
Activity icon

Replied to Can't Downgrade Jquery Version

@shami003 If your app works and npm installed, then leave it be lol. I will add that I had your issue when jquery 3.5.0 came out, but since being on jquery 3.5.1, I have had no issues and have not had to downgrade back to 3.4.1

Jul
11
1 month ago
Activity icon

Replied to Can't Downgrade Jquery Version

@shami003 Try clearing your npm cache after removing the node_modules folder, and be sure you edit the numbers again in package.json. Then npm install again

npm cache clean --force
Jul
09
1 month ago
Activity icon

Replied to Can't Downgrade Jquery Version

@shami003 Try removing your node_modules folder, and delete your package-lock.json, then change the 3.5.1 back to 3.4.1 in your package.json, then npm install again.

Activity icon

Started a new Conversation Passport Custom Login For Access Token

Just curious, when it comes to passport and password grants, I only use them for first party apps/SPA, so instead of extending the base controllers, I wanted to be able to run the logins through the regular login process, so that I may throttle request and reduce the required fields down to just username, password, and client_secret. This way I can also un-register the passport routes and use my own API route for login and refresh token.

Has anyone else done anything similar to this? By default, the oauth/token route does not limit attempts or trigger user login event, so this was my solution:

LoginController

class ApiLoginController extends Controller
{
    /*
    |--------------------------------------------------------------------------
    | API Login Controller
    |--------------------------------------------------------------------------
    |
    | This controller handles authenticating users for the application's API
    |
    */

    use AuthenticatesUsers;

    /**
     * Get the number of minutes to throttle for.
     *
     * @var int
     */
    protected $decayMinutes = 5;

    /**
     * Get the maximum number of attempts to allow.
     *
     * @var int
     */
    protected $maxAttempts = 5;

    /**
     * ApiLoginController constructor.
     */
    public function __construct()
    {
        $this->middleware('guest')->except('logout');
    }

    /**
     * Handle a login request to the application.
     *
     * @param Request $request
     * @return Response|\Symfony\Component\HttpFoundation\Response|void
     * @throws ValidationException
     * @noinspection PhpVoidFunctionResultUsedInspection
     */
    public function login(Request $request)
    {
        $this->validateLogin($request);

        if ($this->hasTooManyLoginAttempts($request))
        {
            $this->fireLockoutEvent($request);

            return $this->sendLockoutResponse($request);
        }

        if ($this->attemptLogin($request))
            return $this->requestAccessToken($request);

        $this->incrementLoginAttempts($request);

        return $this->sendFailedLoginResponse($request);
    }

    /**
     * Request access token from oauth server
     *
     * @param Request $request
     * @return Response
     */
    private function requestAccessToken(Request $request)
    {
        try{
            $this->addTokenRequest($request);

            $dispatchToTokenServer = $this->tokenServer()->issueToken(
                $this->serverRequest()
            );

            $this->authenticated($request, $this->guard()->user());

            $this->clearLoginAttempts($request);

            return $dispatchToTokenServer;

        }catch (Exception $e) {
            throw new HttpException(422, $e->getMessage());
        }
    }

    /**
     * Add oauth params to request before creating server request instance
     *
     * @param Request $request
     */
    private function addTokenRequest(Request $request)
    {
        $request->request->add([
            'grant_type' => 'password',
            'client_id' => config('passport.password_grant_client.id'),
            'client_secret' => $request->input('client_secret'),
            'username' => $request->input('email'),
            'password' => $request->input('password'),
            'scope' => ''
        ]);
    }

    /**
     * Get the AccessTokenController instance
     *
     * @return Application|AccessTokenController|mixed
     */
    private function tokenServer()
    {
        return app(AccessTokenController::class);
    }

    /**
     * Get the ServerRequestInterface instance
     *
     * @return Application|mixed|ServerRequestInterface
     */
    private function serverRequest()
    {
        return app(ServerRequestInterface::class);
    }

    /**
     * Validate the user login request.
     *
     * @param Request $request
     * @return void
     *
     */
    protected function validateLogin(Request $request)
    {
        $request->validate([
            'email' => 'required|string',
            'password' => 'required|string',
            'client_secret' => 'required|string'
        ]);
    }

    /**
     * Get the needed authorization credentials from the request.
     *
     * @param Request $request
     * @return array
     */
    protected function credentials(Request $request)
    {
        return array_merge($request->only('email', 'password'), ['active' => 1]);
    }

    /**
     * Attempt to log the user into the application.
     *
     * @param Request $request
     * @return bool
     */
    protected function attemptLogin(Request $request)
    {
        return $this->guard()->once($this->credentials($request));
    }

    /**
     * Fire the logged in event
     *
     * @param Request $request
     * @param Authenticatable|User $user
     */
    protected function authenticated(Request $request, User $user)
    {
        event(new NewLogin($user, $request->ip()));
    }
}
Activity icon

Replied to Can't Downgrade Jquery Version

@shami003 Remove the carrot to force it to stay on one version.

"dependencies": {
        "admin-lte": "^3.0.5",
        "jquery": "3.4.1"
    }
Jul
04
1 month ago
Activity icon

Awarded Best Reply on I'd Like To Remove The Old Token. (passport, Password Grant)

@yng When a new token is created (any kind of access token), Passport raises an event. You can subscribe for the event and create your own listener to revoke old tokens for the user id and client id https://laravel.com/docs/7.x/passport#events

Example of the revoke listener

<?php

namespace App\Listeners;

use Laravel\Passport\Events\AccessTokenCreated;
use DB;

class RevokeOldTokens
{
    /**
     * The name of the queue the job should be sent to.
     *
     * @var string|null
     */
    public $queue = 'default';

    /**
     * Create the event listener.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Handle the event.
     *
     * @param  AccessTokenCreated  $event
     * @return void
     */
    public function handle(AccessTokenCreated $event)
    {
        DB::table('oauth_access_tokens')
            ->where('id', '<>', $event->tokenId)
            ->where('user_id', $event->userId)
            ->where('client_id', $event->clientId)
            ->update(['revoked' => true]);
    }
}

Event service provider

<?php

namespace App\Providers;

use App\Listeners\RevokeOldTokens;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use Laravel\Passport\Events\AccessTokenCreated;

class EventServiceProvider extends ServiceProvider
{
    /**
     * The event listener mappings for the application.
     *
     * @var array
     */
    protected $listen = [
        AccessTokenCreated::class => [
            RevokeOldTokens::class,
        ],
    ];

    /**
     * Register any events for your application.
     *
     * @return void
     */
    public function boot()
    {
        parent::boot();
    }
}
Activity icon

Replied to I'd Like To Remove The Old Token. (passport, Password Grant)

@yng When a new token is created (any kind of access token), Passport raises an event. You can subscribe for the event and create your own listener to revoke old tokens for the user id and client id https://laravel.com/docs/7.x/passport#events

Example of the revoke listener

<?php

namespace App\Listeners;

use Laravel\Passport\Events\AccessTokenCreated;
use DB;

class RevokeOldTokens
{
    /**
     * The name of the queue the job should be sent to.
     *
     * @var string|null
     */
    public $queue = 'default';

    /**
     * Create the event listener.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Handle the event.
     *
     * @param  AccessTokenCreated  $event
     * @return void
     */
    public function handle(AccessTokenCreated $event)
    {
        DB::table('oauth_access_tokens')
            ->where('id', '<>', $event->tokenId)
            ->where('user_id', $event->userId)
            ->where('client_id', $event->clientId)
            ->update(['revoked' => true]);
    }
}

Event service provider

<?php

namespace App\Providers;

use App\Listeners\RevokeOldTokens;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use Laravel\Passport\Events\AccessTokenCreated;

class EventServiceProvider extends ServiceProvider
{
    /**
     * The event listener mappings for the application.
     *
     * @var array
     */
    protected $listen = [
        AccessTokenCreated::class => [
            RevokeOldTokens::class,
        ],
    ];

    /**
     * Register any events for your application.
     *
     * @return void
     */
    public function boot()
    {
        parent::boot();
    }
}
Activity icon

Awarded Best Reply on When I Made Passport Client(Password Grant Token)

@yng The name is simply so you can give the client something easy to reference by (name), and in case you ever want to pull the name directly to show in a view or through API. The providers is simply asking which "model" the client is linked to for authorization. If you say had users, admins, companies models, you may want different oauth clients to be linked to different auth models. In that case, you would also setup more models in the passport config under the providers array.

Jul
03
1 month ago
Activity icon

Replied to When I Made Passport Client(Password Grant Token)

@yng The name is simply so you can give the client something easy to reference by (name), and in case you ever want to pull the name directly to show in a view or through API. The providers is simply asking which "model" the client is linked to for authorization. If you say had users, admins, companies models, you may want different oauth clients to be linked to different auth models. In that case, you would also setup more models in the passport config under the providers array.

Jul
02
1 month ago
Activity icon

Replied to Best Way To Manage Device FCM Token ?

@michaelnguyen547 On both iOS and Android, you can get the Unique device ID (not the FCM token) and use that on login/register/app wakeup to post FCM token and Device ID, Then in the logic, you can check if you have that device ID, and if you do update to w.e FCM token is sent as well. If new device ID, store new row in DB instead of update. I also let the user id be nullable so that I can link to a user once authed if I collected the device as a guest.

    public function up()
    {
        Schema::create('user_devices', function (Blueprint $table) {
            $table->uuid('user_id')->nullable();
            $table->string('device_id', 255)->unique();
            $table->string('device_token', 255)->unique();
            $table->string('voip_token', 255)->nullable();
            $table->integer('badges')->nullable();
            $table->integer('device_type')->nullable(); //0 = android, 1 = iOS
            $table->timestamps();
            $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade')->onUpdate('cascade');
        });
    }
Jun
30
1 month ago
Activity icon

Replied to Video Call App

My code above is simply a full demo, but not separated into an installable package. You would have to extract out my ideas/code into your own project right now. Assuming you have my prerequisites installed (DB, REDIS, laravel-echo-server), my install docs should work. I am currently in the process of rewriting it from scratch and having a proper API/Documentation for all of my methods.

Activity icon

Replied to Routes Horizon And Websockets

@slickness Horizon already provides an authorization gate on the route you define in their config. Follow their instructions adding the authorize gate in Horizons service provider.

https://laravel.com/docs/7.x/horizon#dashboard-authorization

You can also create your own gates on routes or actions to enforce on whatever route you created for your websocket admin page. You may also create middleware and attach them to the routes as well

https://laravel.com/docs/7.x/authorization#gates https://laravel.com/docs/7.x/middleware#defining-middleware

Jun
29
1 month ago
Activity icon

Replied to Laravel Horizon Install Error

@shuvobhai You are missing the php extension ext-pcntl. Now this extension is NOT supported on windows directly, but if you have Windows Subsystem for Linux installed, you can indeed install that extension through WSL, then you just have to be sure to use WSL terminal when running composer install. This also means if you use artisan serve locally, you must run it through WSL if you wish to actually run horizon locally.

Jun
24
1 month ago
Activity icon

Replied to Is There A Way To Prevent User From Accessing Non-GET Routes?

@chron You can override what you want certain exceptions to do in the Exceptions/Handler.php, for example catch the Method not allowed exception and check if it is a JSON response, otherwise redirect to w.e route you want

    /**
     * Render an exception into an HTTP response.
     *
     * @param  Request  $request
     * @param  Throwable $exception
     * @return Response
     *
     * @throws Throwable
     */
    public function render($request, Throwable $exception)
    {
        if($exception instanceof MethodNotAllowedHttpException){
            if($request->expectsJson()){
                return response()->json([
                    'message' => "Method not allowed"
                ], 405);
            }
            return redirect()->route('home');
        }
            
        return parent::render($request, $exception);
    }
Jun
22
1 month ago
Activity icon

Awarded Best Reply on API Nested Shallow Resource Policy Not Registering Correctly?

One other thing I think you missed is naming the parameter in your constructor, try:

public function __construct()
{
    $this->authorizeResource(MainMachine::class, 'machine');
}

https://laravel.com/docs/7.x/authorization#via-controller-helpers

Jun
21
1 month ago
Activity icon

Replied to API Nested Shallow Resource Policy Not Registering Correctly?

One other thing I think you missed is naming the parameter in your constructor, try:

public function __construct()
{
    $this->authorizeResource(MainMachine::class, 'machine');
}

https://laravel.com/docs/7.x/authorization#via-controller-helpers

Activity icon

Replied to API Nested Shallow Resource Policy Not Registering Correctly?

@rotario Route model bindings must match the type hinted variable name, and in this case it expects MainMachine to be $machine instead of $mainMachine. Try

    public function update(User $user, MainMachine $machine)
    {
        return true;
    }

Be sure the type hints also match in your controller methods

May
23
2 months ago
Activity icon

Replied to How Does Cmgmyr/messenger Do What It Does??

All that is doing is calling extra calls to the database from within the blade files. When it loads the thread model itself in the controller, it does not include any relations at that point. However, if you check the blade files, you will see it load relations such as $thread->messages, and the thread model already has a hasMany relation to the message class. As for the user object, notice it calls $thread->creator()->name. You can trace that back to their Thread model class in the src:

    public function creator()
    {
        if ($this->creatorCache === null) {
            $firstMessage = $this->messages()->withTrashed()->oldest()->first();
            $this->creatorCache = $firstMessage ? $firstMessage->user : Models::user();
        }

        return $this->creatorCache;
    }

Thread model

https://github.com/cmgmyr/laravel-messenger/blob/master/src/Models/Thread.php#L104

Thread blade

https://github.com/cmgmyr/laravel-messenger/blob/master/examples/views/messenger/partials/thread.blade.php#L11

May
09
3 months ago
Activity icon

Replied to Maintenance Mode Exception

Seems you may want to use the Http Kernal.php to throw your own custom message if site is down. I have used this method in the past where I check the exception class thrown and use a switch case to return my own message if is json request, or regular render if not a json request. You can add all the exceptions you want in the switch, such as (TokenMismatchException, ThrottleRequestsException, NotFoundHttpException, etc)

class Handler extends ExceptionHandler
{
    /**
     * @param Exception $exception
     * @return mixed|void
     * @throws Exception
     */
    public function report(Exception $exception)
    {
        parent::report($exception);
    }

    /**
     * Render an exception into an HTTP response.
     *
     * @param Request $request
     * @param Exception $exception
     * @return Response|JsonResponse|RedirectResponse|Redirector
     * @throws Exception
     */
    public function render($request, Exception $exception)
    {
        switch(class_basename($exception)){
            case 'MaintenanceModeException':
                if ($request->expectsJson()){
                    return response()->json(['error' => 'The site is currently down for maintenance, please check back with us soon'], 503);
                }
                return parent::render($request, $exception);
            break;
        }
        if (app()->isProduction()){
            if ($request->expectsJson()){
                return response()->json('Server Error',500);
            }
            return response()->view('errors.500', [], 500);
        }
        return parent::render($request, $exception);
    }
May
08
3 months ago
Activity icon

Replied to Validation Problems

Validate is called on a request as that is where you validate user input. If it passes, you can go down in your store method and create the new tag class. And use the custom rule to write your logic for the lowercase portion. If it passes validation, you can then lowercase it again if you choose before creating tag. https://laravel.com/docs/7.x/validation#quick-writing-the-validation-logic

Activity icon

Replied to Validation Problems

Look into writing your own custom rule you can use in laravels validator. Also, validate is called on a request, and you seem to be calling it on your Tag class.

https://laravel.com/docs/7.x/validation#custom-validation-rules

May
03
3 months ago
Activity icon

Awarded Best Reply on I Don't Receive A Broadcast Message In The Front End Laravel-echo-server

@jorge_dev96 It could be the event name your Echo is listening for. By default laravel will broadcast the event's class name and prepend the namespace as well, so you may be receiving App\Events\NewMessage and did not setup Echo namespace. I prefer to name my events instead using their broadcastAs method. Then in your listener you use your defined name prepended with a "." as such:

NewMessage Event class add

    public function broadcastAs()
    {
        return 'NewMessage';
    }

ChatApp.vue

    Echo.private(`messages.${this.user.id}`)
        .listen('.NewMessage', (e) => {
          console.log(e);
          if (this.selectedContact && e.message.from == this.selectedContact.id){
                    this.saveNewMessage(e.message);
                    alert('fired');
                }
      });
Apr
27
3 months ago
Activity icon

Replied to If Output Of \Log::info Depens On Some Options?

@petrogromovo Calling the log facade will always write a log to your specified log channels. You could wrap it inside your own logging class that checks for ENV or your own custom config flags and runs the Log::info() if met.

class MyLogService
{
    public static function info(string $string, array $context = [])
    {
        if(!app()->isProduction() || config('logging.custom.info'))
            Log::info($string, $context);
    }

    public static function warning(string $string, array $context = [])
    {
        if(!app()->isProduction() || config('logging.custom.warning'))
            Log::warning($string, $context);
    }
}
    $lol = 'ok';
    MyLogService::info($lol)
Apr
25
3 months ago
Activity icon

Awarded Best Reply on How To Send Http Post Request With Timer In Laravel

Look into the docs for the laravel scheduler https://laravel.com/docs/7.x/scheduling

You setup the cronjob that will call artisan schedule each minute

* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1

From there you can tell it when exactly to trigger either a command, job, etc. I personally would create a new custom artisan command that just calls your method in your controller. Then tell the scheduler to call that command at your choosing

$schedule->command('api:store-data')->daily();
Activity icon

Replied to How To Send Http Post Request With Timer In Laravel

Look into the docs for the laravel scheduler https://laravel.com/docs/7.x/scheduling

You setup the cronjob that will call artisan schedule each minute

* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1

From there you can tell it when exactly to trigger either a command, job, etc. I personally would create a new custom artisan command that just calls your method in your controller. Then tell the scheduler to call that command at your choosing

$schedule->command('api:store-data')->daily();
Activity icon

Awarded Best Reply on Detect API Request In Laravel

@dutchman1990 Does your app use different headers or authorization token at all? If it does, you can make a helper function to check the headers for a key. Our app sends Authorization header (for passport) while our web end uses the passport web cookie in the web session, so I just lookout for the Authorization key to know it is app:

if(request()->hasHeader('Authorization')){
    //is from app
}
Apr
24
3 months ago
Activity icon

Replied to Missunderstanding Php Artisan Schedule:run Use

@meredevelopment The scheduler is "dumb" in the sense that it does not know how many times it was called within one minute. What is actually happening is when you call the schedule command, it matches the time on the server and sees if anything matches, and everyMinute() would be called every time you ran it as the time matches a minute of any hour, where everyFiveMinutes would only run at any 5min interval of an hour (1pm, 1:05pm, 1:10pm, etc). If you ran it twice at 1:05pm, you would have fired off twice (everyMinute and everyFiveMinutes). Daily runs when the time matches 12am. The goal is to setup a cronjob that runs the artisan schedule command once per minute on your server. Running locally and triggering manually will always cause the everyMinute to fire, or any matching "times". everyTenMinutes added in would fire all 3 (minute, 5 minute, 10 minute) if the time were 1:10.

Setup the cronjob to hit it once per minute and you are golden :

* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
Activity icon

Awarded Best Reply on POST Http://127.0.0.1:8000/messages 500 (Internal Server Error)

First it looks like your ChatEvent expects a Chat::class, but from your controller it looks like you send it a Message class? Unless you creating a message() is Chat.

Also as per the docs, when you authorize a presence channel, you need to return an array about the user yourself, not the model directly (though I have never tried that)

Broadcast::channel('chat', function ($user) {
    return ['id' => $user->id, 'name' => $user->name];
});

Last note, assuming you are testing on local directly, you may want to go into the broadcasting.php config file and turn encrypted to false in local dev

        'pusher' => [
            'driver' => 'pusher',
            'key' => env('PUSHER_APP_KEY'),
            'secret' => env('PUSHER_APP_SECRET'),
            'app_id' => env('PUSHER_APP_ID'),
            'options' => [
                'cluster' => env('PUSHER_APP_CLUSTER'),
                'encrypted' => false
            ],
        ],