Tuesday, January 8, 2019

Membuat Aplikasi Web Realtime dengan Django, RabbitMQ dan Vue.js Bagian 3: API dengan Django Rest Framework

Membuat Aplikasi Web Realtime dengan Django, RabbitMQ dan Vue.js Bagian 3: API dengan Django Rest Framework - CodePolitan.com

Artikel ini merupakan terjemahan seri tutorial Real time Chat application built with Vue, Django, RabbitMQ and uWSGI WebSockets bagian ketiga yang ditulis oleh Osaetin Daniel.
Daftar isi:
Dibagian sebelumnya kita menggunakan djoser untuk membuat backend sistem otentikasi kita dan menghubungkannya dengan aplikasi Vue.js.

Sekarang kita akan mulai membangun API menggunakan django rest framework. API ini akan memberikan endpoint yang kita butuhkan untuk memulai sesi chat baru, bergabung dengan sesi chat yang sudah ada, mengirimkan pesan lalu mengambil riwayat pesan.

Arsitektur

Sebelum memulai, mari kita diskusikan bagaimana program kita akan berjalan:

Realtime Django 3.1
  • Saat seorang user mengirim pesan, pesan ini akan dikirim ke django lewat API.
  • Setelah django menerima pesan tersebut, ia akan melanjutkannya ke RabbitMQ.
  • RabbitMQ menggunakan sebuah exchange untuk mengirim pesan broadcast ke beberapa queue. Queue ini adalah kanal komunikasi yang akan melanjutkan pesan ke klien. Workers adalah proses yang berjalan di belakang layar untuk melakukan proses broadcasting dan melanjutkan pengiriman pesan.
RabbitMQ adalah perantara dua bagian paling penting diaplikasi kita yaitu Django dan uWSGI. Ia juga membuat aplikasi kita menjadi fleksibel karena python dan django. Ada beberapa cara untuk mengirim pesan ke RabbitMQ, bahkan bisa dikirim dari command line. Ini artinya aplikasi lain tidak perlu tahu sistem aplikasi chat kita untuk berkomunikasi dengannya.

Sebagai contoh, sebuah aplikasi desktop yang ditulis dalam bahasa C# dapat mengirim pesan ke queue RabbitMQ dan pesannya tetap akan diterima oleh klien kita.
Tanpa RabbitMQ, server WebSocket uWSGI tidak tahu apa-apa tentang aplikasi django kita (bagaimana mengakses database, melakukan otentikasi, dll) karena ia berjalan di proses yang berbeda mungkin juga di server web yang berbeda tergantung konfigurasi yang dilakukan.
  • uWSGI berfungsi sebagai server websocket. Setelah klien terhubung dan kanal yang sesuai (RabbitMQ exchange) dapat menerima pesan, kita akan membaca pesan tersebut begitu diterima lalu langsung mengirimkannya ke user dengan WebSocket.
Untuk aplikasi Vue, server development webpack dapat menjadi solusi yang tepat saat karena kita baru mengembangkannya komputer lokal. Nanti jika aplikasi ini akan dideploy, kita bisa menjalankan perintah npm build yang akan menghasilkan static file untuk dijalankan oleh web server (Nginx, Apache bahkan github pages)

Implementasi

Dibagian ini, tujuan akhir kita ialah untuk mengimplementasi API dengan django rest framework. API ini akan mengijinkan user memulai sesi chat baru, bergabung dengan sesi yang sudah ada dan mengirim pesan. Kita juga bisa mengambil riwayat pesan dari sebuah sesi chat.

Mari buat app django yang baru bernama chat:
$ python manage.py startapp chat

Jangan lupa mengambahkannya ke INSTALLED_APPS.

Selanjutnya, kita akan membuat model untuk data pesan, sesi chat juga user-user yang terhubung. Mari buat model ini di models.py.

"""Models for the chat app."""

from uuid import uuid4

from django.db import models
from django.contrib.auth import get_user_model

User = get_user_model()

def deserialize_user(user):
    """Deserialize user instance to JSON."""
    return {
        'id': user.id, 'username': user.username, 'email': user.email,
        'first_name': user.first_name, 'last_name': user.last_name
    }

class TrackableDateModel(models.Model):
    """Abstract model to Track the creation/updated date for a model."""

    create_date = models.DateTimeField(auto_now_add=True)
    update_date = models.DateTimeField(auto_now=True)

    class Meta:
        abstract = True

        def _generate_unique_uri():
                """Generates a unique uri for the chat session."""
                return str(uuid4()).replace('-', '')[:15]

class ChatSession(TrackableDateModel):
    """
        A Chat Session.

        The uri's are generated by taking the first 15 characters from a UUID
        """

                owner = models.ForeignKey(User, on_delete=models.PROTECT)
                uri = models.URLField(default=_generate_unique_uri)

class ChatSessionMessage(TrackableDateModel):
    """Store messages for a session."""

    user = models.ForeignKey(User, on_delete=models.PROTECT)
    chat_session = models.ForeignKey(
        ChatSession, related_name='messages', on_delete=models.PROTECT
    )
    message = models.TextField(max_length=2000)

    def to_json(self):
        """deserialize message to JSON."""
        return {'user': deserialize_user(self.user), 'message': self.message}

class ChatSessionMember(TrackableDateModel):
    """Store all users in a chat session."""

    chat_session = models.ForeignKey(
        ChatSession, related_name='members', on_delete=models.PROTECT
    )
    user = models.ForeignKey(User, on_delete=models.PROTECT)
 
Pastikan menjalankan migrasi database sebelum melanjutkan agar tabel-tabelnya dibuat.
Langkah selanjutnya ialah dengan membuat view (endpoint API) yang memungkinkan user untuk memanipulasi data ke server.
Kita bisa mengatur django rest framework untuk membuatnya (kita tidak memakai serializer karena modelnya masih sederhana). Mari kita tulis kode di bawah pada file views.py

"""Views for the chat app."""

from django.contrib.auth import get_user_model
from .models import (
    ChatSession, ChatSessionMember, ChatSessionMessage, deserialize_user
)

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import permissions

class ChatSessionView(APIView):
    """Manage Chat sessions."""

    permission_classes = (permissions.IsAuthenticated,)

    def post(self, request, *args, **kwargs):
        """create a new chat session."""
        user = request.user

        chat_session = ChatSession.objects.create(owner=user)

        return Response({
            'status': 'SUCCESS', 'uri': chat_session.uri,
            'message': 'New chat session created'
        })

    def patch(self, request, *args, **kwargs):
        """Add a user to a chat session."""
        User = get_user_model()

        uri = kwargs['uri']
        username = request.data['username']
        user = User.objects.get(username=username)

        chat_session = ChatSession.objects.get(uri=uri)
        owner = chat_session.owner

        if owner != user:  # Only allow non owners join the room
            chat_session.members.get_or_create(
                user=user, chat_session=chat_session
            )

        owner = deserialize_user(owner)
        members = [
            deserialize_user(chat_session.user) 
            for chat_session in chat_session.members.all()
        ]
        members.insert(0, owner)  # Make the owner the first member

        return Response ({
            'status': 'SUCCESS', 'members': members,
            'message': '%s joined that chat' % user.username,
            'user': deserialize_user(user)
        })

class ChatSessionMessageView(APIView):
    """Create/Get Chat session messages."""

    permission_classes = (permissions.IsAuthenticated,)

    def get(self, request, *args, **kwargs):
        """return all messages in a chat session."""
        uri = kwargs['uri']

        chat_session = ChatSession.objects.get(uri=uri)
        messages = [chat_session_message.to_json() 
            for chat_session_message in chat_session.messages.all()]

        return Response({
            'id': chat_session.id, 'uri': chat_session.uri,
            'messages': messages
        })

    def post(self, request, *args, **kwargs):
        """create a new message in a chat session."""
        uri = kwargs['uri']
        message = request.data['message']

        user = request.user
        chat_session = ChatSession.objects.get(uri=uri)

        ChatSessionMessage.objects.create(
            user=user, chat_session=chat_session, message=message
        )

        return Response ({
            'status': 'SUCCESS', 'uri': chat_session.uri, 'message': message,
            'user': deserialize_user(user)
        })
 
Method patch untuk ChatSessionView bersifat idempotent karena memanggil rikues yang sama berkali-kali akan menghasilkan data yang sama pula. Itu artinya, user dapat bergabung ke sebuah chat room berkali-kali tapi hanya akan ada satu objek user yang sama didalam respon (termasuk di dalam tabel database).

Hal lain yang perlu diingat tentang method patch ialah ia akan mengembalikan pemilik chat room sebagai seorang member tapi di dalam database kita tidak akan menambahkan pemilik itu sebagai member room, kita hanya mengambil informasinya dan mengirimnya kembali ke aplikasi klien. Tidak perlu ada duplikasi data dengan menambahkan pemilik room sebagai membernya di database.

Kita dapat dengan mudah mengambil info user didalam method patch dengan memanggil request.user tapi pemanggilan ini hanya akan memperbanyak perintah SELECT di database.
Begini skenario sederhananya, apa yang akan terjadi jika kita memutuskan untuk mengundang teman berdasarkan username ke sebuah sesi chat. Dengan request.user kita tidak bisa melakukannya karena request.user akan merujuk pada user yang sekarang sedang melakukan rikues.

Sebaliknya, dengan username, kita cukup mengirimkan username tersebut ke serber dan server akan menggunakannya untuk mengambil user yang sesuai lalu menambahkannya ke chat room.

Lalu, jika ingin melakukan "invite multiple users", kita dapat memodifikasi kode tadi untuk mengambil sebuah list username dan menggunakannya untuk mengambil data-data dari database.

Intinya, menggunakan username membuat kode lebih fleksibel untuk pengembangan di masa mendatang.
Sekarang mari tambahkan URL untuk views yang sudah dibuat ke urls.py di app chat:

"""URL's for the chat app."""

from django.contrib import admin
from django.urls import path

from . import views

urlpatterns = [
    path('chats/', views.ChatSessionView.as_view()),
    path('chats/<uri>/', views.ChatSessionView.as_view()),
    path('chats/<uri>/messages/', views.ChatSessionMessageView.as_view()),
]

Jangan lupa untuk menambahkan URL app chat ke file urls.py utama:

from django.contrib import admin
from django.uris import path, include

uripatterns = [
    path('admin/', admin.site.uris),

    # Custom URL's
    path('auth/', include('djoser.uris')),
    path('auth/', include('djoser.uris.authtoken')),
    path('api/', include('chat.uris'))
]
 
Sekarang endpoint kita sudah siap dan semua user yang melakukan login dapat membuat rikues baru.
Mari kita coba di terminal:

$ curl -X POST http://127.0.0.1:8000/auth/token/create/ --data 'username=danidee&password=mypassword'
{"auth_token":"169fcd5067cc55c500f576502637281fa367b3a6"}

$ curl -X POST http://127.0.0.1:8000/api/chats/ -H 'Authorization: Token 169fcd5067cc55c500f576502637281fa367b3a6'
{"status":"SUCCESS","uri":"040213b14a02451","message":"New chat session created"}

$ curl -X POST http://127.0.0.1:8000/auth/users/create/ --data 'username=daniel&password=mypassword'
{"email":"","username":"daniel","id":2}

$ curl -X POST http://127.0.0.1:8000/auth/token/create/ --data 'username=daniel&password=mypassword'
{"auth_token":"9c3ea2d194d7236ac68d2faefba017c8426a8484"}

$ curl -X PATCH http://127.0.0.1:8000/api/chats/040213b14a02451/ --data 'username=daniel' -H 'Authorization: Token 9c3ea2d194d7236ac68d2faefba017c8426a8484'
{"status":"SUCCESS","members":[{"id":1,"username":"danidee","email":"osaetindaniel@gmail.com","first_name":"","last_name":""},{"id":2,"username":"daniel","email":"","first_name":"","last_name":""}],"message":"daniel joined that chat","user":{"id":2,"username":"daniel","email":"","first_name":"","last_name":""}}

Selanjutnya kita coba mengirim pesan:

$ curl -X POST http://127.0.0.1:8000/api/chats/040213b14a02451/messages/ --data 'message=Hello!' -H 'Authorization: Token 169fcd5067cc55c500f576502637281fa367b3a6'
{"status":"SUCCESS","uri":"040213b14a02451","message":"Hello!","user":{"id":1,"username":"danidee","email":"osaetindaniel@gmail.com","first_name":"","last_name":""}}

$ curl -X POST http://127.0.0.1:8000/api/chats/040213b14a02451/messages/ --data 'message=Hey whatsup!' -H 'Authorization: Token 9c3ea2d194d7236ac68d2faefba017c8426a8484'
{"status":"SUCCESS","uri":"040213b14a02451","message":"Hey whatsup! i dey","user":{"id":2,"username":"daniel","email":"","first_name":"","last_name":""}}

Terakhir kita coba membaca riwayat pesan:

$ curl http://127.0.0.1:8000/api/chats/040213b14a02451/messages/ -H 'Authorization: Token 169fcd5067cc55c500f576502637281fa367b3a6'
{"id":1,"uri":"040213b14a02451","messages":[{"user":{"id":1,"username":"danidee","email":"osaetindaniel@gmail.com","first_name":"","last_name":""},"message":"Hello!"},{"user":{"id":2,"username":"daniel","email":"","first_name":"","last_name":""},"message":"Hey whatsup!"}]}

Selamat! Kita sudah berhasil membangun API yang memungkinkan user untuk berkomunikasi satu sama lain lewat sesi chat dan mengundah user lain untuk bergabung dengan sesi chat.

Selanjutnya kita akan membangun UI aplikasi chat (Vue) dan memanggil method-method di atas didalamnya.

Kode akhirnya bisa dilihat di Github.

Sumber : CODEPOLITAN

Monday, January 7, 2019

Awal Tahun Baru 2019, GitHub Gratiskan Repositori Privat

Awal Tahun Baru 2019, GitHub Gratiskan Repositori Privat - CodePolitan.com

Tepat seminggu di tahun baru 2019, pada tanggal 7 Januari Github secara resmi mengumumkan perubahan struktur fitur yang ditawarkan untuk akun gratis, akun pro dan akun Enterprise berbayar. Salah satu fitur yang paling menarik untuk ditengok adalah repositori privat unlimited untuk akun gratis.

Repositori Privat Unlimited

Sebelumnya, akun gratis (GitHub Free) hanya memberikan jatah repositori publik yang unlimited. Jika membutuhkan repositori tertutup, kita wajib menggunakan akun berbayar sehingga membuat banyak developer memanfaatkan layanan hosting git yang lain seperti Bitbucket

Agar para developer tetap setia menggunakan Github untuk keperluan penyimpanan kode sumber tertutup, misalnya untuk pekerjaan sampingan atau tugas sekolah (TA, Skripsi, dsb.), akun gratis sekarang dapat membuat repositori privat unlimited.

Akun Enterprise Cloud Terpadu

Akun berbayar yang sebelumnya bernama GitHub Business Cloud kini berubah nama menjadi Enterprise Cloud dan Enterprise Server (sebelumnya GitHub Enterprise). 

Perusahaan yang ingin menggunakan Github di server sendiri dapat memanfaatkan kedua layanan tadi secara terpadu. Berkat GitHub Connect, developer dapat bekerja dari kedua environment tadi secara bersamaan dengan aman.

GitHub Pro

GitHub Pro yang dulunya bernama GitHub Developer dan GitHub Team masih tersedia untuk developer maupun tim yang membutuhkan fitur kolaborasi professional. Bedanya dengan akun gratis, GitHub pro bisa memiliki unlimited kolaborator untuk repositori publik maupun privat, sedangkan akun gratis hanya bisa 3 kolaborator untuk repositori privat.

Fitur lain yang tidak tersedia di akun gratis yang tersedia di GitHub Pro adalah tools untuk melakukan code review.

Penutup

Meski melahirkan kontroversi saat pengakuisisian oleh Microsoft beberapa waktu lalu, GitHub membuktikan bahwa mereka masih berada di jalan yang benar dan tentunya masih memperhatikan para pengguna setia. Dengan perubahan ini, GitHub berharap semua developer, baik itu yang baru belajar ngoding maupun developer yang sudah bekerja secara profesional dapat menggunakan dan memanfaatkan semua kecanggihan GitHub untuk dunia yang lebih baik.

Sumber: blog.github.com 

Awal Tahun Baru 2019, GitHub Gratiskan Repositori Privat

Sunday, January 6, 2019

Laravel 5.6 Akan Mendukung Algoritma Password Hashing Argon2i

Laravel 5.6 Akan Mendukung Algoritma Password Hashing Argon2i - CodePolitan.com

Pada tahun 2013 yang lalu, ahli kriptografi dan praktisi keamanan diseluruh dunia berkumpul untuk melaksanakan Password Hashing Competition (PHC) dengan tujuan untuk mendapatkan satu atau lebih fungsi password hashing sebagai standar yang direkomendasikan.
Pada bulan Juli tahun 2015, Argon2 yang didesain oleh Alex Biryukov, Daniel Dinu, dan Dmitry Khovratovich dari University of Luxembourg terpilih sebagai pemenang final PHC. Argon2 memiliki tiga versi:
  • Argon2d memaksimalkan pertahanan dari GPU cracking attack.
  • Argon2i dioptimasi untuk menahan side-channel attacks. Ia mengakses memory array dalam urutan yang password yang independen.
  • Argon2id adalah versi hibrida. Ia mengikuti pendekatan Argon2i untuk pengiriman pertama ke memori lalu menggunakan pendekatan Argon2d dilangkah selanjutnya.
Dengan dirilisnya PHP 7.2 pada bulan November tahun 2017, PHP sekarang memiliki fungsi baik untuk versi 2d maupun i. Namun, versi 2d kurang cocok untuk password hashing.

Laravel 5.6 yang akan keluar bulan depan sekarang akan memiliki dukungan Argon2i password hashing berkat bantuan Michael Lundbøl, dan pembaca dapat mengetahui bagaimana fungsi ini diimplementasi ke dalam Laravel melalui pull request berikut.

Solusi pendahulu menggunakan bcrypt tetap akan didukung dan tetap menjadi fungsi bawaan, tapi jika pembaca membuat project baru dan ingin mencoba Argon2i driver, tunggu hingga Laravel 5.6 dirilis secara resmi.

Sumber: Laravel News CODEPOLITAN

Membuat Aplikasi Web Realtime dengan Django, RabbitMQ dan Vue.js Bagian 2: Otentikasi dan Manajemen User

Membuat Aplikasi Web Realtime dengan Django, RabbitMQ dan Vue.js Bagian 2: Otentikasi dan Manajemen User - CodePolitan.com

Artikel ini merupakan terjemahan seri tutorial Real time Chat application built with Vue, Django, RabbitMQ and uWSGI WebSockets bagian kedua yang ditulis oleh Osaetin Daniel.

Kita akan mulai pembuatan chatire dengan melakukan implementasi manajemen user dan otentikasi sehingga user bisa membuat akun baru dan melakukan login.

Berkat komunitas Django yang luar biasa, hal-hal tadi sudah tersedia untuk kita pakai. Oleh karena itu kita akan menggunakan pustaka django pihak ketiga bernama djoser

Mari kita pasang dari pypi
pip install djangorestframework
pip install djoser
Djoser adalah implementasi sistem otentikasi Django berbasis REST. Jadi dengan pustaka ini kita akan mendapatkan endpoint REST untuk melakukan registrasi user, pembuatan token, manajemen user dll.

Konfigurasi djoser

Kita mulai dengan konfigurasi palign sederhana untuk djoser. Tambahkan kode berikut di INSTALLED_APPS
INSTALLED_APPS = (
    'django.contrib.auth',
    ...,
    'rest_framework',
    'rest_framework.authtoken',
    'djoser',
)
lalu url djoser di urls.py:
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    ...,
    path('auth/', include('djoser.urls')),
    path('auth/', include('djoser.urls.authtoken')),
]
Masukkan rest_framework.authentication.TokenAuthentication ke dalam kelas otentikasi django rest:
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.TokenAuthentication',
        (...)
    ),
}

Terakhir, jalankan migrasi database dengan perintah python manage.py migrate. Perintah ini akan membuat tabel-tabel yang dibutuhkan djsoer.

Hanya dengan menambah kode-kode di atas sekarang endpoint otentikasi sudah siap. Mari kita buat user baru (jalankan di terminal):
curl -X POST http://127.0.0.1:8000/auth/users/create/ --data 'username=danidee&password=mypassword'

{"email":"","username":"danidee","id":1}
Voila! Sekarang kita sudah memiliki use baru. Lihat dokumentasi djoser untuk semua endpoint yang tersedia dan bagaimana cara menggunakannya di 

http://djoser.readthedocs.io/en/latest/base_endpoints.html

Vue.js

Vue adalah Framework JavaScript untuk membuat antarmuka yang Reactive. Meskipun penulis merupakan fans berat React (karena React-native), penulis lebih memilih Vue untuk membuat aplikasi web.

Salah satu alasannya ialah kurva belajar yang lebih bersahabat. Ia lebih mudah untuk mulai dipelajari dan tidak seperti React dimana kita harus bersusah payah menyiapkan banyak hal (dengan Webpack dan kawan-kawannya) untuk membuat aplikasi yang production ready. Pembaca cukup menulis tag <script> seperti saat akan menggunakan JQuery.
Ia juga memiliki komunitas yang giat dengan banyak plugin dan tutorial yang tersedia.

Kita akan memakai vue-cli untuk membuat Vue app dengan cepat (tidak menggunakan tag <script>). Methode ini memungkinkan kita untuk menggunakan ES6+ dan single file Vue component.
Pasang vue-cli dari npm:
npm install -g vue-cli

Mari mulai proyek baru menggunakan webpack dengan vue-cli
vue init webpack chatire-frontend

Catatan: Pastikan memilih opsi “install vue-router”

Sekarang mungkin waktu yang tepat untuk membuat secangkir kopi atau mengambil snack karena prosesnya dapat memakan waktu lama tergantung kecepatan internet kita.

Selanjutnya, masuk ke direktori aplikasi vue yang sudah muncul (diterminal dengan perintah cd) dan jalankan server development dengan perintah:
npm run dev.
Seharusnya saat membuka alamat localhost:8080 di browser kita akan melihat:

Realtime Django 2.1

Mari kita bahas sebentar struktur foldernya:
.
├── build
│   ├── build.js
│   ├── check-versions.js
│   ├── logo.png
│   ├── utils.js
│   ├── vue-loader.conf.js
│   ├── webpack.base.conf.js
│   ├── webpack.dev.conf.js
│   └── webpack.prod.conf.js
├── config
│   ├── dev.env.js
│   ├── index.js
│   ├── prod.env.js
│   └── test.env.js
├── index.html
├── node_modules
├── package.json
├── package-lock.json
├── README.md
├── src
│   ├── App.vue
│   ├── assets
│   │   └── logo.png
│   ├── components
│   ├── main.js
│   └── router
│       └── index.js
├── static
└── test
    ├── e2e
    │   ├── custom-assertions
    │   │   └── elementCount.js
    │   ├── nightwatch.conf.js
    │   ├── runner.js
    │   └── specs
    │       └── test.js
    └── unit
        ├── jest.conf.js
        ├── setup.js
        └── specs
            └── HelloWorld.spec.js
  • build: Direktori ini berisi skrips yang dipakai untuk menjalankan server development webpack atau bundel aplikasi saat siap dipakai di production. Contoh, perintah npm run dev sebetulnya memanggil perintah:
    webpack-dev-server --inline --progress --config build/webpack.dev.conf.js
    Opsi --inline memasukkan file static yang di generate ke halaman index.html.
  • config: Sesuai namanya, disini tempat menyimpan file-file yang berhubungan dengan konfigurasi development, testing dan production
  • src: Disini adalah tempat menulis sebagian besar kode-kode yang kita perlukan, ia memiliki subfolder yang yang memiliki fungsi masing-masing.
    Component single file kita akan disimpan di folder ini. Akan ada satu component bawaan bernama HelloWorld.vue.
    File index.js di folder router memiliki konfigurasi untuk vue-router.
  • static: File static (HTML, CSS and JavaScript) disimpan di folder ini.
  • test: Terakhir, template webpack dari vue-cli akan mempermudah ini jika ingin melakukan pengujian aplikasi dengan membuat End to end tests (e2e) di atas Nightwatch dan unit tests yang berjalan dengan Jest.
    Pengujian yang ada dapat dijalankan dengan perintah npm run unit (untuk unit tests) dan npm run e2e untuk End to end tests.
vue-cli juga menyiapkan fitur hotreloading untuk kita untuk membantu kita sehingga tidak perlu melakukan refresh di browser.

Konfigurasi Vue router

Buat dua component, satu untuk halaman utama bernama Chat.vue dan satu lagi untuk User Authentication dan Signup bernama UserAuth.vue
Idealnya apa yang kita inginkan adalah menampilkan component berdasarkan status Login user. Jika User sudah melakukan Login, maka kita ingin menampilkan component Chat jika tidak kita ingin menampilkan component UserAuth.

Kita dapat melakukannya dengan menggunakan global navigation. Edit file router index.js agar memiliki kode sebagai berikut:
import Vue from 'vue'
import Router from 'vue-router'
import Chat from '@/components/Chat'
import UserAuth from '@/components/UserAuth'

Vue.use(Router)

const router = new Router({
  routes: [
    {
      path: '/chats',
      name: 'Chat',
      component: Chat
    },

    {
      path: '/auth',
      name: 'UserAuth',
      component: UserAuth
    }
  ]
})

router.beforeEach((to, from, next) => {
  if (sessionStorage.getItem('authToken') !== null || to.path === '/auth') {
    next()
  }
  } else {
    next('/auth')
  }
})

export default router
Method beforeEach dipanggil sebelum melakukan navigasi ke route manapun diaplikasi kita.

Jika sebuah token disimpan di dalam sessionStorage kita akan memperbolehkan navigation melanjutkan pekerjaannya dengan memanggil next() jika tidak kita kembali ke component auth.
Ke mana pun route yang dituju oleh user di aplikasi kita, fungsi ini akan memeriksa jika user memiliki auth token dan membawanya sesuai tujuan.

Halaman Login/Signup

Penulis sudah membuat halaman Login/Signup sederhana dengan Bootstrap 4. Berikut isi konten UserAuth.vue:
<template>
  <div class="container">
    <h1 class="text-center">Welcome to Chatire!</h1>
    <div id="auth-container" class="row">
      <div class="col-sm-4 offset-sm-4">
        <ul class="nav nav-tabs nav-justified" id="myTab" role="tablist">
          <li class="nav-item">
            <a class="nav-link active" id="signup-tab" data-toggle="tab" href="#signup" role="tab" aria-controls="signup" aria-selected="true">Sign Up</a>
          </li>
          <li class="nav-item">
            <a class="nav-link" id="signin-tab" data-toggle="tab" href="#signin" role="tab" aria-controls="signin" aria-selected="false">Sign In</a>
          </li>
        </ul>

        <div class="tab-content" id="myTabContent">

          <div class="tab-pane fade show active" id="signup" role="tabpanel" aria-labelledby="signin-tab">
            <form @submit.prevent="signUp">
              <div class="form-group">
                <input v-model="email" type="email" class="form-control" id="email" placeholder="Email Address" required>
              </div>
              <div class="form-row">
                <div class="form-group col-md-6">
                  <input v-model="username" type="text" class="form-control" id="username" placeholder="Username" required>
                </div>
                <div class="form-group col-md-6">
                  <input v-model="password" type="password" class="form-control" id="password" placeholder="Password" required>
                </div>
              </div>
              <div class="form-group">
                <div class="form-check">
                  <input class="form-check-input" type="checkbox" id="toc" required>
                  <label class="form-check-label" for="gridCheck">
                    Accept terms and Conditions
                  </label>
                </div>
              </div>
              <button type="submit" class="btn btn-block btn-primary">Sign up</button>
            </form>
          </div>

          <div class="tab-pane fade" id="signin" role="tabpanel" aria-labelledby="signin-tab">
            <form @submit.prevent="signIn">
              <div class="form-group">
                <input v-model="username" type="text" class="form-control" id="username" placeholder="Username" required>
              </div>
              <div class="form-group">
                <input v-model="password" type="password" class="form-control" id="password" placeholder="Password" required>
              </div>
              <button type="submit" class="btn btn-block btn-primary">Sign in</button>
            </form>
          </div>

        </div>
      </div>
    </div>
  </div>
</template>

<script>
  const $ = window.jQuery // JQuery

  export default {

    data () {
      return {
        email: '', username: '', password: ''
      }
    }

  }
</script>

<style scoped>
  #auth-container {
    margin-top: 50px;
  }

  .tab-content {
    padding-top: 20px;
  }
</style>

Pada sisipan kode di atas, v-model dipakai untuk melakukan two way data binding untuk semua kolom input. Ini artinya apapun yang kita tulis di kolom tersebut dapat langsung diakses dari JavaScript menggunakan this.field_name.

Kita juga membuat event listeners di kedua form menggunakan @submit.prevent yang akan mendengarkan event form submitdari setiap form dan memanggil method yang diinginkan. Kita belum mengimplementasi method-method tersebut.
Karena kita menggunakan Bootstrap, daripada memanggil jQuery dari npm kita menggunakan variabel $ untuk mendaftarkan window.jQuery secara global.

Kita akan memakai method ajax jQuery untuk berkomunikasi dengan server. Silahkan gunakan pustaka ajax lain seperti Axios jika tidak ingin menggunakan jQuery. Pustaka ini cukup populer dikalangan pengguna Vue.

Jangan lupa untuk menambahkan include file-file CSS dan JavaScript Bootstrap di halaman index.html.
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.3/css/bootstrap.min.css" integrity="sha384-Zug+QiDoJOrZ5t4lssLdxGhVrurbmBWopoEl+M6BdEfwnCJZtKxi1KgxUyJq13dy" crossorigin="anonymous">

    <style>
      .nav-tabs .nav-item.show .nav-link, .nav-tabs .nav-link.active {
        outline: none;
      }
    </style>

    <title>chatire-frontend</title>
  </head>
  <body>
    <div id="app"></div>
    <!-- built files will be auto injected -->

    <script src="https://code.jquery.com/jquery-3.2.1.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.3/js/bootstrap.min.js" integrity="sha384-a5N7Y/aK3qNeh15eJKGWxsqtnX/wWdSZSKp+81YjTmS15nvnvxKHuzaWwXHDli+4" crossorigin="anonymous"></script>
  </body>
</html>
Hasil yang didapat seharusnya:

Realtime Django 1.2
Cukup oke kan?


Mari Kita Ambil auth token dari Django

Ktia ingin mendaftarkan user, memasukkannya dan membawanya ke route Chat.

Untuk melakukannya, kita harus mengimplement method signUp dan signIn di kode sebelumnya:
methods: {
  signUp () {
    $.post('http://localhost:8000/auth/users/create/', this.$data, (data) => {
      alert("Your account has been created. You will be signed in automatically")
      this.signIn()
    })
    .fail((response) => {
      alert(response.responseText)
    })
  },

  signIn () {
    const credentials = {username: this.username, password: this.password}

    $.post('http://localhost:8000/auth/token/create/', credentials, (data) => {
      sessionStorage.setItem('authToken', data.auth_token)
      sessionStorage.setItem('username', this.username)
      this.$router.push('/chats')
    })
    .fail((response) => {
      alert(response.responseText)
    })
  }
}

Sekarang coba submit form tadi. Oops! Ada kesalahan:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:8000/auth/users/create. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).

CORS

Menurut situs Mozilla:
Cross-Origin Resource Sharing (CORS) is a mechanism that uses additional HTTP headers to let a user agent gain permission to access selected resources from a server on a different origin (domain) than the site currently in use. A user agent makes a cross-origin HTTP request when it requests a resource from a different domain, protocol, or port than the one from which the current document originated.
Secara sederhana CORS memperbolehkan rikues Ajax dari domain tertentu untuk melakukan XmlHttpRequest. Normalnya kita tidak bisa melakuakn XmlHttpRequest dari situs dengan domain yang berbeda (catatan: jika ada yang salah harap dikoreksi).

Dalam kasus ini, meskipun sama-sama berjalan di localhost, karena berjalan di port yang berbeda (8080 dan 8000) mereka dianggap berada di domain yang berbeda.

Domain yang memiliki skema (http atau https), hostname (localhost) dan port yang harus sama pula.

Jadi bagaimana cara menjalankan CORS di aplikasi django? Ada pustaka pihak ketiga untuk memudahkan hal tersebut bernama django-cors-headers.
pip install django-cors-headers
tambahkan di INSTALLED_APPS
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    # Custom Apps
    'rest_framework',
    'rest_framework.authtoken',
    'corsheaders',
    'djoser'
]
tambahkan juga di (Pastikan ditulis sebelum django.middleware.common.CommonMiddleware)
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',

    'corsheaders.middleware.CorsMiddleware',

    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
Terakhir atur CORS_ORIGIN_ALLOW_ALL = True


Catat bahwa apa yang kita lakukan mengaktifkan CORS untuk semua domain. Ini boleh dilakukan untuk development tapi saat di production kita mungkin hanya ingin domain tertentu saja

CORS_ORIGIN_WHITELIST

Baca dokumentasi django-cors-header untuk melihat opsi lain.
Setelah melakukannya, kita sekarang bisa membuat akun dan melakukan login.

Dibelakang layar, django-cors-headers menggunakan sebuah Middleware untuk menambah header ke setiap rikues yang memberitahu Django bahwa rikues tersebut aman dan boleh dilakukan.

Logout

Karena kita memakai sessionStorage untuk menyimpan auth token, kita bisa memulai session baru dengan membuka tab baru.
Jika ingin menyimpan token di tab baru atau saat browser di restart kita bisa memakai localStorage. Ia memiliki API yang sama dengan sessionStorage sehingga kita cukup mengganti session ke local.

Lalu kita dapat membuat sebuah fugnsi yang mengapus token dari storage dengan memanggil removeItem. Berikut kode untuk melakukannya dengan localStorage.
localStorage.removeItem('authToken')

Kesimpulan

Tutorial kali ini cukup sampai manajemen user dan sistem otensikasi. Kita mulai dengan memasang djoser, sebuah pustaka django yang memberikan endpoint REST untuk otentikasi.

Kita juga menggunakan method ajax milik jQuery untuk memanggil endpoints tersebut.

Selanjutnya kita membahas Same origin policy sedikit dan belajar bagaimana memperbolehkan rikues Ajax dari aplikasi Vue ke backend Django menggunakan CORS lewat django-cors-headers.

Dibagian berikutnya, kita membuat model django dan API untuk aplikasi Chat.

Sumber : Membuat Aplikasi Web Realtime dengan Django, RabbitMQ dan Vue.js Bagian 2: Otentikasi dan Manajemen User

Saturday, January 5, 2019

Membuat Aplikasi Web Realtime dengan Django, RabbitMQ dan Vue.js Bagian 1: Persiapan

Membuat Aplikasi Web Realtime dengan Django, RabbitMQ dan Vue.js Bagian 1: Persiapan - CodePolitan.com


Artikel ini merupakan terjemahan serti tutorial Real time Chat application built with Vue, Django, RabbitMQ and uWSGI WebSockets bagian pertama yang ditulis oleh Osaetin Daniel.

Prasyarat

Tutorial ini bukan pengenalan untuk Django maupun Vue.
Untuk bisa mendapatkan manfaat dari tutorial ini, pembaca sudah harus familiar dengan Django. Setidaknya pernah mencoba Getting Started guide dan contoh Polling app.

Pembaca juga sudah harus nyaman membuat kode-kode JavaScritp terutama sudah mengetahui dasar-dasar penggunaan Vue.js. Kita tidak akan membuat aplikasi SPA yang kompleks dengan Vue, tapi jika belum familiar silahkan kunjungi halaman dokumentasinya.

Jika sudah pernah mencoba React atau Angular seharusnya pembaca tidak akan menemukan masalah saat mencoba kode-kode Vue karena ia meminjam banyak konsep dari keduanya (terutama React).

Penulis akan mencoba menjelaskan bagian-bagian yang penulis rasa cukup rumit atau banyak hal ajaib yang terjadi.
Jika ada yang tidak dimengerti silahkan tanyakan melalui komentar.


Pustaka yang digunakan

Python:
JavaScript:

Apa yang akan kita pelajari?

  • Tujuan utama tutorial ini adalah mengenalkan pembaca akan WebSockets dan bagaimana mengintegrasikannya dengan aplikasi django.
  • Saat mengikuti tutorial ini kita juga akan membuat “pusher versi minimalis” dengan RabbitMQ untuk mengirimkan pesan broadcast secara realtime ke beberapa klien.
  • Tidak hanya itu, kita juga akan membangun sistem otentikasi berbasis token sehingga bisa menghubungkan aplikasi SPA Vue.js dengan backend django-rest-framework. Ada banyak tutorial Vue.js diluar sana (yang membahas otentikasi berbasis token) tapi sebagian besar menggunakan Laravel atau NodeJS.
Sebelum lanjut, berikut ini kurang lebih tampilan aplikasi yang akan kita buat:

Realtime Django 1.2

Penulis namakan aplikasi ini chatire tapi pembaca bisa menamainya sendiri.

Pemasangan

Sebelum mulai pastikan sudah membuat sebuah virtual environment dan mengaktifkannya


Lalu pasang django dengan perintah:
$ pip install django
selanjutnya buat project baru bernama chatire.
$ django-admin startproject chatire
jalankan migrations migrations
$ python manage.py migrate
Terakhir, mulai django development server dengan perintah:
$ python manage.py runserver
Jika semua berjalan dengan semestinya pembaca akan melihat:

Realtime Django 1.2

Landing page Django 2.0 terlihat sangat bagus!

Bagian berikutnya kita akan mengimplementasi registrasi user dan otentikasi menggunakan djoser.
Repo tutorial ini juga tersedia di Github.

Sumber : CODEPOLITAN

Mengaktifkan Fitur Font Ligature dengan Fira Code

Mengaktifkan Fitur Font Ligature dengan Fira Code - CodePolitan.com

Dalam tipografi, font ligatures adalah sebuah konsep menggabungkan karakter yang berdekatan menjadi satu. Beberapa font seperti Fira Code memiliki fitur ini. Sebagian besar editor dan IDE juga sudah mendukung fitur ini. Penggunaan font ligatures secara teknis memang tidak memberikan pengaruh apa-apa kepada program, tapi ia membantu memberikan gambaran simbol-simbol penting yang ditampilkan berbeda dengan yang lain.

Di tutorial ini kita akan memasang fitur font ligatures ke Visual Studio Code dan keluarga IntelliJ (Android Studio, PhpStorm, PyCharm, WebStorm, dkk.).

Pertama, kita harus memasang Fira Code dulu (banyak font lain yang mendukung font ligatures tapi penulis memilih Fira Code karena gratis dan cukup populer).

Pengguna Ubuntu bisa langsung memasangnya dengan perintah sudo apt install fonts-firacode. Sistem Linux lain mungkin memiliki cara khusus untuk memasangnya. Jika tidak, cukup download file .ttf dan masukkan ke folder ~/.fonts dan jalankan perintah fc-cache.

Untuk pengguna Windows dan Mac, silahkan pasang seperti pemasangan font pada umumnya.

Visual Studio Code

Buka aplikasi Visual Studio Code, lalu klik File > Preferences > Settings (atau CTRL + ,). Pilih file User Settings dan tambahkan dua baris berikut:
{
    "editor.fontFamily": "Fira Code",
    "editor.fontLigatures": true
}


IntelliJ dan Kawan-kawan

Buka File > Settings > Editor > Color & Fonts > Font. Pilih Fira Code dibagian Primary Font dan klik Enable font ligatures.

Penutup

Untuk editor yang lain caranya tidak jauh berbeda. Pembaca hanya perlu mencari file settings dan mengaktifkan opsi font ligatures.
Semoga artikel ini bermanfaat.

Sumber : Mengaktifkan Fitur Font Ligature dengan Fira Code

Menggunakan Intention Action di Android Studio (Sulap ALT+ENTER)

Menggunakan Intention Action di Android Studio (Sulap ALT+ENTER) - CodePolitan.com

Android Studio merupakan salah satu IDE dengan fitur paling canggih saat ini. IDE yang dikembangkan Google dari IntelliJ ini menjadi andalan Android Developer saat bekerja. Bagaimana tidak, Android Studio memiliki fitur-fitur yang dibuat khusus untuk mempermudah pekerjaan seorang Android Developer. Salah satu fiturnya yang sangat membantu adalah intention action.

Apa Itu Intention Action

Intention action sebetulnya adalah fitur dari IntelliJ. Fitur ini mempermudah developer saat akan membuat kelas yang belum ada, membuat method yang belum ditulis, membungkus kode ke dalam blok try-catch, dst.
Oleh Google, Android Studio diberikan intention action tambahan untuk menyelesaikan hal-hal tambahan yang berhubungan langsung dengan pengembangan aplikasi Android. Misalnya melakukan ekstrak string, dimension, layout, color, dll.

Bagaimana Cara Menggunakannya?

Untuk menggunakan intention action ada dua cara. Cara pertama dengan menggunakan ALT+ENTER.


Lalu cara yang kedua dengan memilih (klik) gambar ikon lampu yang akan muncul (biasanya di sebelah kiri baris kode).


Kapan Menggunakannya?

Pada umumnya kita dapat menggunakan intention action saat melihat gambar-gambar ikon berikut ini:

ItemIconDescription
Intention actions suggestedintentionBulbLampu kuning menandakan bahwa ada saran yang lebih baik untuk kode yang sudah kita tulis (peringatan). Jika tidak diikuti program akan tetap berjalan seperti biasa.
Specific intention actionicon intentionActionEnabledSimbol ini memberikan daftar intention action yang lebih spesifik dan dapat dilakukan kapan saja dan bisa memilih untuk men-disable action tertentu.
Quickfix suggestedquickfixBulbLampu merah menandakan bahwa terjadi kesalahan dan Android Studio dapat memberikan sebuah solusi untuk menyelesaikannya. Tidak semua kesalahan dapat langsung diselesaikan begitu saja dengan ini.
DisabledintentionBulbGreyAction di disable namun masih tersedia dan bisa di enable-kan lagi.

Kesimpulannya, intention action dapat sangat membantu menyelesaikan permasalahan dengan cepat atau memberikan solusi kode yang lebih baik. Namun, tidak semua bisa diselesaikan secara langsung dengan fitur ini sehingga kita sebagai developer Android masih harus memperhatikan action apa saja yang bisa dilakukan dengan seksama.

Referensi: https://www.jetbrains.com/help/idea/intention-actions.html

CODEPOLITAN

Rekomendasi Aplikasi Penghasil Cuan :D Dirumah saja tetap Dapet Duit !!!

Hallo Bosskyuuh semua. Perkenalkan aku Patrick Ananta berasal dari Jawa Tengah. Aku sudah lama sekali dirumahkan dikarenakan covid19 sehingg...