Skip to content

nasrulhazim/training-2024-07-chirps-mbsa

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

53 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Bootcamp Laravel - Chirps

Refer to https://bootcamp.laravel.com/blade/installation.

Day 1

Setup API

php artisan install:api

Create Chirp API Controllers:

php artisan make:controller Api/ChirpController --api

Define API Route for Chirp in routes/api.php:

<?php

use App\Http\Controllers\Api\ChirpController;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;

Route::get('/user', function (Request $request) {
    return $request->user();
})->middleware('auth:sanctum');

Route::get('/chirps', [ChirpController::class, 'index']);

Create Chirp resource & collection:

php artisan make:resource ChirpResource
php artisan make:resource ChirpCollection

Disable data wraping in resource:

<?php

namespace App\Providers;

use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     */
    public function register(): void
    {
        //
    }

    /**
     * Bootstrap any application services.
     */
    public function boot(): void
    {
        JsonResource::withoutWrapping();
    }
}

Return list of chirps in Api/ChirpController in index:

return new ChirpCollection(Chirp::all());

Return chirp details in Api/ChirpController in show:

return new ChirpResource(Chirp::findOrFail($id));

Day 2

Setup auth API endpoints - login, register & logout

Update your the OpenAPI Specification for Chirps API as in here.

Create new controller for handling Auth related:

php artisan make:controller Api/AuthController

Then update the controller as in here.

Update the routes/api.php:

<?php

use App\Http\Controllers\Api\AuthController;
use App\Http\Controllers\Api\ChirpController;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;

Route::get('/user', function (Request $request) {
    return $request->user();
})->middleware('auth:sanctum');

Route::post('/register', [AuthController::class, 'register']);
Route::post('/login', [AuthController::class, 'login']);
Route::middleware('auth:sanctum')->group(function () {
    Route::post('/logout', [AuthController::class, 'logout']);
});

Route::get('/chirps', [ChirpController::class, 'index']);
Route::get('/chirps/{chirp}', [ChirpController::class, 'show']);

In app/Models/User.php, add HasApiTokens trait:

use Laravel\Sanctum\HasApiTokens;

class User extends Authenticatable
{
    use HasFactory, Notifiable, HasApiTokens;

Next, open up your Insomnia, create new collection. Import collection from here.

Then open up the Enviroment settings, update base environment as following:

 {
 "scheme": "http",
 "base_path": "/api",
 "host": "127.0.0.1",
 "bearerToken": "bearerToken",
 "base_url": "{{ _.scheme }}://{{ _.host }}{{ _.base_path }}"
}

Now you can test your API endpoints for register, login and logout.

React App

php artisan config:publish cors

Set the in config/cors.php:

'supports_credentials' => true,

Unit Test (Pest)

Install Pest:

composer remove phpunit/phpunit
composer require pestphp/pest --dev --with-all-dependencies

Setup Pest:

on Linux / Mac:

./vendor/bin/pest --init

on Windows, run:

vendor\bin\pest.bat --init

Create API unit test:

php artisan make:test ApiTest --pest

Update your unit test as in here.

To run the unit test, specifically to tests/Feature/ApiTest.php:

vendor/bin/pest tests/Feature/ApiTest.php

or on Windows:

vendor\bin\pest.bat tests/Feature/ApiTest.php

Day 8

Artisan Command

Create artisan command:

php artisan make:command ReloadAllCachesCommand

Then update the codes as in here.

To use the command:

php artisan reload:caches

Mail

Create mail class:

php artisan make:mail WelcomeMail

Update class as in here.

Create view for welcome mail:

php artisan make:view mail.welcome

Update the mail view as in here.

Use routes/console.php, copy as in here.

Test the email:

php artisan test:mail

Open your browser at http://127.0.0.1:8025 to see new welcome email.

Create Markdown Mail

php artisan make:mail ThankYou --markdown

Update the view as in here.

Use routes/console.php, copy as in here.

Notification

Create notifications table.

php artisan make:notifications-table
php artisan migrate

Create notification class:

php artisan make:notification WelcomeNotification --markdown=notifications.welcome

Then update our app/Notifications/WelcomeNotification.php as in here.

Then update the view for the notifications as in here.

Send notification, by update routes/console.php as in here.

php artisan test:notify

Event & Listener

Create listener for registered user event:

php artisan make:listener SendWelcomeNotification --event=\\Illuminate\\Auth\\Events\\Registered

Update the listener as in here.

Then go and register new account. Any new registration will get notification.

Practice

Create an artisan command which send daily quote to all users. Make use of the custom artisan command, notification, event & listeners.

php artisan make:command SendDailyQuoteCommand
php artisan make:notification SendQuoteNotification --markdown=notifications.quote
php artisan make:event SendQuote
php artisan make:listener SendQuoteNotification --event=SendQuote

Passport Integration

.env Configuration

Update .env to point to OAuth Server(Laravel Passport), the Client ID and Secret which generated using php artisan passport:client command in OAuth Server and redirect URI which to handle the authentication process after approval from OAuth Server.

# OAuth Server URL
OAUTH_SERVER_URL=http://127.0.0.1:8000

# App's client id and secret

## Get this value from php artisan passport:client - Client ID
OAUTH_CLIENT_ID=

## Get this value from php artisan passport:client - Client Secret
OAUTH_CLIENT_SECRET=

# App's callback / redirect URL
OAUTH_REDIRECT_URI=http://127.0.0.1:8001/oauth/callback

Handling OAuth

In config/services.php, add the following:

'passport' => [
    'url' => env('OAUTH_SERVER_URL'),
    'client_id' => env('OAUTH_CLIENT_ID'),
    'client_secret' => env('OAUTH_CLIENT_SECRET'),
    'redirect_url' => env('OAUTH_REDIRECT_URI'),
],

In routes/web.php, disable the following section by comment it:

// Route::get('/', function () {
//     return view('welcome');
// });

In routes/auth.php, add the following codes, which handle the OAuth process:

/**
 * Handle OAuth
 */
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Http;

Route::get('/', function () {
    $query = http_build_query([
        'client_id' => config('services.passport.client_id'),
        'redirect_uri' => config('services.passport.redirect_uri'),
        'response_type' => 'code',
        'scope' => '',
    ]);

    // redirect to OAuth Server, then require to login/register.
    // after that require to authorize the chirper app to access.
    return redirect(
        config('services.passport.url') . '/oauth/authorize?' . $query
    );
});

Route::get('/oauth/callback', function (Request $request) {
    // get the access token
    $response = Http::asForm()->post(config('services.passport.url') . '/oauth/token', [
        'grant_type' => 'authorization_code',
        'client_id' => config('services.passport.client_id'),
        'client_secret' => config('services.passport.client_secret'),
        'redirect_uri' => config('services.passport.redirect_uri'),
        'code' => $request->code,
    ]);

    try {
        $data = $response->json();
        $accessToken = data_get($data, 'access_token');

        // use access token to get user's details
        $response = Http::withToken($accessToken)->get(config('services.passport.url') . '/api/user');

        abort_if(! $response->ok(), 'Invalid Crendentials');

        $data = $response->json();

        // if user's not exists, create it, else retrieve it.
        if(! User::where('email', data_get($data, 'email'))->exists()) {
            $user = User::create([
                'name' => data_get($data, 'name'),
                'email' => data_get($data, 'email'),
                'password' => Hash::make(date('Ymd').rand(1,10000))
            ]);
        } else {
            $user = User::where('email', data_get($data, 'email'))->first();
        }

        // login user
        Auth::login($user);

        // redirect to profile page.
        return redirect('profile');

    } catch (\Throwable $th) {
        abort(401, $th->getMessage());
    }
});

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages