Membuat Aplikasi Ekspedisi Lumen 6 #4: Cors Handling & Fetch LoggedIn User

Membuat Aplikasi Ekspedisi Lumen 6 #4: Cors Handling & Fetch LoggedIn User

Pendahuluan

Melengkapi materi sebelumnya, dimana kita akan menemui beberapa masalah ketika mengintegrasikan antara API dengan NuxtJS-nya atau mungkin nantinya juga akan ditemui ketika mengintegrasi dengan Svelte. Materi ini akan membahas bagaimana cara melakukan cors handling di Lumen dan kita akan membuat fitur lainnya, yakni mengambil data atau fetching data user yang sedang login dan membuat fitur logout di Lumen.

Luputnya penulis dalam mengingat bahwa masalah ini akan ditemukan dikemudian hari, sehingga kita tidak membahasnya pada artikel sebelumnya. Tapi sebuah bentuk kesyukuran karena bisa menjadi sebuah materi baru lagi. Jadi, apabila kedepannya teman-teman bingung dalam mengikuti rangkaian materinya, saya akan menyertakan link materi sebelumnya pada pendahuluan.

Baca Juga: Membuat Aplikasi Ekspedisi Lumen 6 #3: Validation & Login

Cors Handling di Lumen

Sebuah permasalahan baru akan kita hadapi ketika mengerjakan sebuah aplikasi dengan project yang berbeda antara backend dalam hal ini adalah API dan frontend-nya. Masalah ini disebabkan karena browser meminta authority dari sumber data, apakah domain ini atau project ini diberikan izin untuk mengambil data atau tidak.

Ada beberapa teknik yang bisa dilakukan dalam meng-handle cors, salah satunya melalui backend itu sendiri dengan memberikan response berupa header. Berdasarkan aplikasi yang kita miliki, untuk memberikan headers kepada semua request yang masuk, maka kita akan menggunakan Middleware. Mengapa menggunakan Middleware? Karena akan sangat merepotkan, jika setiap method harus kita sertakan sebuah headers secara manual.

Middleware akan kita manfaatkan untuk menerapkan sebuah aturan secara global, sehingga aturan ini akan diikut sertakan pada semua route yang ada. Buat middleware baru bernama CorsMiddleware.php di dalam folder app/Http/Middleware dan tambahkan code berikut

<?php

namespace App\Http\Middleware;

use Closure;

class CorsMiddleware
{
    /**
     * Run the request filter.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
       //RULE HEADERSNYA HARUS KITA SET SECARA SPESIFIK SEPERTI INI 
        $headers = [
            'Access-Control-Allow-Origin'      => '*',
            'Access-Control-Allow-Methods'     => 'POST, GET, OPTIONS, PUT, DELETE',
            'Access-Control-Allow-Credentials' => 'true',
            'Access-Control-Max-Age'           => '86400',
            'Access-Control-Allow-Headers'     => 'Content-Type, Authorization, X-Requested-With'
        ];
        
        //TAPI JIKA METHOD YANG MASUK ADALAH OPTIONS
        if ($request->isMethod('OPTIONS')) {
            //MAKA KITA KEMBALIKAN BAHWA METHOD TERSEBUT ADALAH OPTIONS
            return response()->json('{"method": "OPTIONS"}', 200, $headers);
        }

        //SELAIN ITU, KITA AKAN MENERUSKAN RESPONSE SEPERTI BIASA DENGAN MENGIKUT SERTAKAN HEADERS YANG SUDAH DITETAPKAN.
        $response = $next($request);
        foreach ($headers as $key => $row) {
            $response->header($key, $row);
        }
        return $response;
    }

}

Untuk mengaktifkan Middleware ini, buka file bootstrap/app.php dan tambahkan code

$app->middleware([
    App\Http\Middleware\CorsMiddleware::class
]);

Fetch Logged In & Logout User

Authentication yang akan kita terapkan di NuxtJS memiliki sebuah rule dimana ketika authentication tersebut berhasil, maka dia akan secara otomatis melakukan fetching users yang sedang login. Hal ini luput dari ingatan saya sehingga tidak dituliskan pada artikel sebelumnya.

Adapun cara untuk membuat fitur fetching data user yang sedang login, buka file UserController.php dan tambahkan method berikut

public function getUserLogin(Request $request)
{
    return response()->json(['status' => 'success', 'data' => $request->user()]);
}

Penjelasan: $request->user() akan mengambil data user yang sedang login.

Definisikan routing-nya dengan menambahkan code berikut di dalam file routes/web.php

$router->get('/users/login', 'UserController@getUserLogin');

$router->post('/logout', 'UserController@logout'); //KITA TAMBAHKAN ROUTE LOGOUT SEKALIAN

aplikasi ekspedisi lumen - get user login

Kemudian skenario untuk logout-nya adalah kita akan mengubah value api_token dari user yang sedang login menjadi null. Buka kembali file UserController.php dan tambahkan method

public function logout(Request $request)
{
    $user = $request->user(); //GET USER YANG SEDANG LOGIN
    $user->update(['api_token' => null]); //UPDATE VALUENYA JADI NULL
    return response()->json(['status' => 'success']);
}

[ISSUE] Token Authorization

Ada sedikit masalah ketika format authorization yang dikirim memiliki lebih dari 1 spasi diantara kata Bearer dan token-nya itu sendiri. Masalah tersebut adalah fungsi explode akan menghasilkan lebih dari 2 array, sehingga array dengan key 1 bukan berisi token tapi string kosong.

Untuk mengatasi hal ini, buka file AuthServiceProvider.php yang berada di dalam folder app/Providers dan modifikasi block code yang memiliki return statement menjadi.

return User::where('api_token', end($explode))->first();

Penjelasan: Fungsi end adalah built-in dari PHP, dimana akan mengambil value dari index array terakhir.

[ISSUE] Routing Users

Ada sedikit permasalahan yang akan kita temukan berkaitan dengan fungsi untuk mengambil data user. Routing antara get user berdasarkan id dan get user berdasarkan yang sedang login akan saling tumpang tindih jika posisi route dari user yang sedang login berada di bawah route untuk mengambil user berdasarkan id. Adapun errornya akan terlihat seperti berikut

aplikasi ekspedisi lumen - change order routing

Untuk mengatasinya, cukup ganti posisinya dimana route user login ditempatkan di atas route get user. Buka file routes/web.php dan modifikasi menjadi

$router->get('/users', 'UserController@index');
$router->post('/users', 'UserController@store');
$router->get('/users/login', 'UserController@getUserLogin'); //PINDAHKAN ROUTE INI 
$router->get('/users/{id}', 'UserController@edit'); // DI ATAS ROUTE INI
$router->put('/users/{id}', 'UserController@update');
$router->delete('/users/{id}', 'UserController@destroy');

[ISSUE] Delete Data Users

Kendala yang akan kita temukan ketika melakukan penghapusan data pada user yang tidak memiliki gambar atau foto adalah sebuah response error pada code unlink karena fungsi ini tidak menemukan data gambar yang akan dihapus. So, untuk mengatasinya, buka file UserController.php dan modifikasi method destroy menjadi

public function destroy($id)
{
    $user = User::find($id);
    if ($user->photo) {
        unlink(base_path('public/images/' . $user->photo));
    }
    $user->delete();
    return response()->json(['status' => 'success']);
}

[ISSUE] Validation on Update Users

Password adalah bagian penting bersifat opsional pada fitar edit data user, karena data password melalui proses encrypt, sehingga kita menggunakan logic dimana ketika password kosong, maka tidak perlu untuk memperbaharui data tersebut. Seluruh logic ini sudah direalisasikan, akan tetapi pada bagian validasi, kita lupa menghapus atau mengubahnya menjadi nullable, sehingga data password masih bersifat required.

Untuk mengatasinya, modifikasi line validasi password pada method update menjadi

'password' => 'nullable|string|min:6',

[ISSUE] Search Data Users

Salah satu fitur yang terlupakan ketika membuat API data users pada episode Lumen adalah fitur pencarian data berdasarkan nama users. Sangat disayangkan jika materi ini harus diangkat pada materi baru, sehingga fitur ini saya anggap sebagai issue saja, jadi dalam penulisan bisa disisipkan pada seri yang sudah release.

Buka file UserController.php dan modifikasi method index menjadi

public function index(Request $request)
{
    $users = User::orderBy('created_at', 'desc')->when($request->q, function($users) use($request) {
        $users = $users->where('name', 'LIKE', '%' . $request->q . '%');
    })->paginate(10);
    return response()->json(['status' => 'success', 'data' => $users]);
}

 

Baca Juga: Membuat Aplikasi Ekspedisi Lumen 6 #2: Authentication & Manage Users

Kesimpulan

Sepanjang artikel ini kita telah belajar banyak hal baru ketika mengerjakan sebuah aplikasi, dimana masalah yang biasanya ditemukan seperti cors handling sudah berhasil kita selesaikan dengan lancar. Kita juga telah belajar bagaimana mengambil data user yang sedang login dan lain sebagainya.

Adapun dokumentasi code dari artikel ini bisa dilihat di Github.

 

Category:
Share:

Comments