API Rest with Laravel 5.6 Passport Authentication — Generate avatar (Part 3)(ok)

https://medium.com/modulr/api-rest-with-laravel-5-6-passport-authentication-generate-avatar-part-3-d92ec7935eff

Ví dụ đã thực hiện

Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhdWQiOiIxIiwianRpIjoiMTgzYWU0ZDljNDM2MDczZTNmMTdiYjIyZTA3OGJhYzA1MTMyMmMwMDllZjlmMTNiYzM3N2RkYjg3ODljOWY0NTJkNTIwYTE5NDU4ZTIyYjIiLCJpYXQiOjE1OTU5NTU3MzUsIm5iZiI6MTU5NTk1NTczNSwiZXhwIjoxNjI3NDkxNzM1LCJzdWIiOiIzIiwic2NvcGVzIjpbXX0.uUXU0huvU1aJnwp4muC5xvJyRsMbxd1nl0nVayBxjhMJoKur0hN9VooYC4cODq85KAptzMuUpoamDim3JvyIvQWNf4AjkxsHtDVRUCLZIsqbUAyB2ER5KKigOUNzBBIO7b3p2oWOPMyh-mkHqkrErcw20_IH79ukrDcXvDqRXpZyyxY4tFc7oxkOyHj34FAP3jfROasrYnrCjs09ph9GPWbMBd1QxOYjGk8H1U7-Tnzgj_-_gbkDOCkbZDd2OwhX_tnhGuFzfocpdWQMtn31hgXB21Rnxys7ndiC62EvWYwYTMG0K2rv5U2xp8hZMMmX8ZU6hdaViCvUrGKX2-lNe_ms4u6W7HGNp8qTlsIH_pq6wlY28_lo2W3YyYdzt4wTceLPZXRekvRiZ3Q6gzzNBbcNE_o4uO2yDDtNYC2snQNeoThTIWK8Bqe6PIpVDabtH6Q46vDH0-qaxG8IVWUkWHblVB6qGS-Q50WVWIQ_tTfEnlGx4sXG0OPCDRbpZ4VDH3ho8tMV2dMJuJOxa2NNL-wNGNLhplJ2LUUt2qkmHbRLlY9nbhyhmHdj5K2PtJcbysArxUPEFGckjRuMnWwUslUAo_s-fwcaNA-xClL5sKdC6KJr-gmz_IAvl1h3iKoNzUeYbSirxBJv-c-3oTbd2A6__6jMXBiQMAMW7GHCBUk
{
    "id": 3,
    "name": "Lionel1",
    "email": "phamngoctuong1805@gmail.com",
    "avatar": "avatar.png",
    "active": 1,
    "created_at": "2020-07-28T16:54:53.000000Z",
    "updated_at": "2020-07-28T16:55:47.000000Z",
    "deleted_at": null,
    "avatar_url": "/storage/avatars/3/avatar.png"
}

C:\xampp\htdocs\avatar\config\auth.php

'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],

        'api' => [
            // 'driver' => 'token',
            'driver' => 'passport',
            'provider' => 'users',
            'hash' => false,
        ],
    ],

C:\xampp\htdocs\avatar\database\migrations\2014_10_12_000000_create_users_table.php

<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateUsersTable extends Migration {
  /**
   * Run the migrations.
   *
   * @return void
   */
  public function up() {
    Schema::create('users', function (Blueprint $table) {
     $table->increments('id');
      $table->string('name');
      $table->string('email')->unique();
      $table->string('password');
      $table->string('avatar')->default('avatar.png');
      $table->boolean('active')->default(false);
      $table->string('activation_token');
      $table->rememberToken();
      $table->timestamps();
      $table->softDeletes();
    });
  }
  /**
   * Reverse the migrations.
   *
   * @return void
   */
  public function down() {
    Schema::dropIfExists('users');
  }
}

C:\xampp\htdocs\avatar\config\app.php


    'providers' => [

        /*
         * Laravel Framework Service Providers...
         */
        Laravel\Passport\PassportServiceProvider::class,
        Illuminate\Auth\AuthServiceProvider::class,
        Illuminate\Broadcasting\BroadcastServiceProvider::class,
        Illuminate\Bus\BusServiceProvider::class,
        Illuminate\Cache\CacheServiceProvider::class,
        Illuminate\Foundation\Providers\ConsoleSupportServiceProvider::class,
        Illuminate\Cookie\CookieServiceProvider::class,
        Illuminate\Database\DatabaseServiceProvider::class,
        Illuminate\Encryption\EncryptionServiceProvider::class,
        Illuminate\Filesystem\FilesystemServiceProvider::class,
        Illuminate\Foundation\Providers\FoundationServiceProvider::class,
        Illuminate\Hashing\HashServiceProvider::class,
        Illuminate\Mail\MailServiceProvider::class,
        Illuminate\Notifications\NotificationServiceProvider::class,
        Illuminate\Pagination\PaginationServiceProvider::class,
        Illuminate\Pipeline\PipelineServiceProvider::class,
        Illuminate\Queue\QueueServiceProvider::class,
        Illuminate\Redis\RedisServiceProvider::class,
        Illuminate\Auth\Passwords\PasswordResetServiceProvider::class,
        Illuminate\Session\SessionServiceProvider::class,
        Illuminate\Translation\TranslationServiceProvider::class,
        Illuminate\Validation\ValidationServiceProvider::class,
        Illuminate\View\ViewServiceProvider::class,

        /*
         * Package Service Providers...
         */

        /*
         * Application Service Providers...
         */
        App\Providers\AppServiceProvider::class,
        App\Providers\AuthServiceProvider::class,
        // App\Providers\BroadcastServiceProvider::class,
        App\Providers\EventServiceProvider::class,
        App\Providers\RouteServiceProvider::class,

    ],

C:\xampp\htdocs\avatar\routes\api.php

<?php
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
Route::group([
    'prefix' => 'auth'
], function () {
    Route::post('login', 'AuthController@login');
    Route::post('signup', 'AuthController@signup');
    Route::get('signup/activate/{token}', 'AuthController@signupActivate');
  
    Route::group([
      'middleware' => 'auth:api'
    ], function() {
        Route::get('logout', 'AuthController@logout');
        Route::get('user', 'AuthController@user');
    });
});

C:\xampp\htdocs\avatar\app\Http\Controllers\AuthController.php

<?php
namespace App\Http\Controllers;
use App\Notifications\SignupActivate;
use App\Notifications\SignupActivated;
use App\User;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Avatar;
use Storage;
class AuthController extends Controller {
  /**
   * Create user
   *
   * @param  [string] name
   * @param  [string] email
   * @param  [string] password
   * @param  [string] password_confirmation
   * @return [string] message
   */
   public function signup(Request $request)
    {
        $request->validate([
            'name' => 'required|string',
            'email' => 'required|string|email|unique:users',
            'password' => 'required|string|confirmed'
        ]);

        $user = new User([
            'name' => $request->name,
            'email' => $request->email,
            'password' => bcrypt($request->password),
            'activation_token' => str_random(60)
        ]);

        $user->save();

        $avatar = Avatar::create($user->name)->getImageObject()->encode('png');
        Storage::put('avatars/'.$user->id.'/avatar.png', (string) $avatar);

        $user->notify(new SignupActivate($user));

        return response()->json([
            'message' => __('auth.signup_success')
        ], 201);
    }
 public function signupActivate($token)
    {
        $user = User::where('activation_token', $token)->first();

        if (!$user) {
            return response()->json([
                'message' => __('auth.token_invalid')
            ], 404);
        }

        $user->active = true;
        $user->activation_token = '';
        $user->save();

        $user->notify(new SignupActivated($user));

        return $user;
    }
  /**
   * Login user and create token
   *
   * @param  [string] email
   * @param  [string] password
   * @param  [boolean] remember_me
   * @return [string] access_token
   * @return [string] token_type
   * @return [string] expires_at
   */
  public function login(Request $request)
    {
        $request->validate([
            'email' => 'required|string|email',
            'password' => 'required|string',
            'remember_me' => 'boolean'
        ]);

        $credentials = request(['email', 'password']);
        $credentials['active'] = 1;
        $credentials['deleted_at'] = null;

        if(!Auth::attempt($credentials))
            return response()->json([
                'message' => __('auth.login_failed')
            ], 401);

        $user = $request->user();

        $tokenResult = $user->createToken('Personal Access Token');
        $token = $tokenResult->token;

        if ($request->remember_me)
            $token->expires_at = Carbon::now()->addWeeks(1);

        $token->save();

        return response()->json([
            'access_token' => $tokenResult->accessToken,
            'token_type' => 'Bearer',
            'expires_at' => Carbon::parse($tokenResult->token->expires_at)->toDateTimeString()
        ]);
    }

 public function logout(Request $request)
    {
        $request->user()->token()->revoke();

        return response()->json([
            'message' => __('auth.logout_success')
        ]);
    }

    /**
     * Get the authenticated User
     *
     * @return [json] user object
     */
    public function user(Request $request)
    {
        return response()->json($request->user());
    }
}

C:\xampp\htdocs\avatar\app\User.php

<?php
namespace App;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Passport\HasApiTokens;
use Storage;
class User extends Authenticatable {
  use Notifiable, HasApiTokens;
  /**
   * The attributes that are mass assignable.
   *
   * @var array
   */
  protected $appends = ['avatar_url']; 
  protected $fillable = [
    'name', 'email', 'password', 'active', 'activation_token', 'avatar'
  ];
  /**
   * The attributes that should be hidden for arrays.
   *
   * @var array
   */
  protected $hidden = [
    'password', 'remember_token', 'activation_token'
  ];
  /**
   * The attributes that should be cast to native types.
   *
   * @var array
   */
  protected $casts = [
    'email_verified_at' => 'datetime',
  ];
   public function getAvatarUrlAttribute()
    {
        return Storage::url('avatars/'.$this->id.'/'.$this->avatar);
    }
}

C:\xampp\htdocs\avatar\app\Notifications\SignupActivate.php

<?php

namespace App\Notifications;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;

class SignupActivate extends Notification
{
    use Queueable;

    /**
     * Create a new notification instance.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Get the notification's delivery channels.
     *
     * @param  mixed  $notifiable
     * @return array
     */
    public function via($notifiable)
    {
        return ['mail'];
    }

    /**
     * Get the mail representation of the notification.
     *
     * @param  mixed  $notifiable
     * @return \Illuminate\Notifications\Messages\MailMessage
     */
    public function toMail($notifiable)
    {
        $url = url('/api/auth/signup/activate/'.$notifiable->activation_token);    
        return (new MailMessage)
        ->subject('Confirm your account')
        ->line('Thanks for signup! Please before you begin, you must confirm your account.')
        ->action('Confirm Account', url($url))
        ->line('Thank you for using our application!');
    }

    /**
     * Get the array representation of the notification.
     *
     * @param  mixed  $notifiable
     * @return array
     */
    public function toArray($notifiable)
    {
        return [
            //
        ];
    }
}

API Rest with Laravel 5.6 Passport Authentication — Generate avatar (Part 3)

Step 1. Install Avatar Package

In first step, we require install to Laravolt Avatar package using bellow command, So open your terminal or command prompt and run bellow command:

composer require laravolt/avatar

We can publish the config service provider (Optional)

php artisan vendor:publish --provider="Laravolt\Avatar\ServiceProvider"

This will create config file located in config/laravolt/avatar.php

Step 2. Add column in users table

We add a column avatar in database/migrations/xxxx_create_users_table.phpmigration file.

<?phpuse Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;class CreateUsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');
            $table->string('email')->unique();
            $table->string('password');
            $table->string('avatar')->default('avatar.png');
            $table->boolean('active')->default(false);
            $table->string('activation_token');
            $table->rememberToken();
            $table->timestamps();
            $table->softDeletes();
        });
    }
...

Next, we add fillable attribute in your App\User model.

<?php...class User extends Authenticatable
{
    ...    protected $fillable = [
        ... 'password', 'active', 'activation_token', 'avatar'
    ];}

After, open your terminal or command prompt and run bellow command:

php artisan migrate:refresh

Step 3. Create avatar for user account

We have to update app/Http/Controllers/AuthController.php controller and update signup api method. So let’s update AuthController and put bellow code:

<?php
use Avatar;
use Storage;
class AuthController extends Controller
{
...    public function signup(Request $request)
    {
        $request->validate([
            'name' => 'required|string',
            'email' => 'required|string|email|unique:users',
            'password' => 'required|string|confirmed'
        ]);        $user = new User([
            'name' => $request->name,
            'email' => $request->email,
            'password' => bcrypt($request->password),
            'activation_token' => str_random(60)
        ]);        $user->save();        $avatar = Avatar::create($user->name)->getImageObject()->encode('png');
        Storage::put('avatars/'.$user->id.'/avatar.png', (string) $avatar);        $user->notify(new SignupActivate($user));        return response()->json([
            'message' => 'Successfully created user!'
        ], 201);
    }
}

Step 4. Get avatar of authenticated user

Finally, we add appends attribute in your App\Usermodel to get avatar url.

<?php...
use Storage;
class User extends Authenticatable
{
    ...    
    protected $appends = ['avatar_url'];   
     public function getAvatarUrlAttribute()
    {
        return Storage::url('avatars/'.$this->id.'/'.$this->avatar);
    }
}

Now we are ready to run our example so run bellow command to quick run:

php artisan serve

Tests

Now, we can simple test by rest client tools (Postman), So I test it and you can see below screenshots.

In this api you have to set two header as listed below:

Content-Type: application/json
X-Requested-With: XMLHttpRequest

Signup

Login

User

Thanks for reading! I’m Alfredo Barrón, Feel free to connect with me via Twitter.

Part 1. Passport Authentication Part 2. Confirm account + notifications Part 3. Generate avatar Part 4. Reset Password Part 5. Send Notifications with Queues on Redis

Resources

-GitHub -Postman collections -Laravolt Avatar

Last updated