Tujuannya adalah untuk membangun aplikasi obrolan dengan set fitur lengkap menggunakan ABly Realtime dalam kombinasi dengan layanan lain untuk menyimpan, memanipulasi, dan berbagi data.
Jika Anda memiliki pertanyaan, ide atau ingin berkontribusi, silakan angkat masalah atau hubungi kami.
Node 16 diinstal
Runtime fungsi Azure dari NPM. Untuk menginstal menjalankan ini:
npm install -g azure-functions-core-tools@4
file .env di ./api:
JWT_SIGNING_KEY=key used to sign tokens for users. Can be anything you decide it to be
# Ably
ABLY_API_KEY=YOURKEY:HERE
APP_ID=[YOUR ABLY APP ID](https://faqs.ably.com/how-do-i-find-my-app-id)
CONTROL_KEY=[YOUR ABLY CONTROL KEY](https://ably.com/documentation/control-api#authentication)
# Azure
COSMOS_ENDPOINT=https://yourcosomsdb.documents.azure.com
COSMOS_KEY=ASK FOR THIS OR MAKE YOUR OWN
COSMOS_DATABASE_ID=metadata
AZURE_STORAGE_CONNECTION_STRING=your string here
AZURE_STORAGE_CONTAINER_NAME=container name here
# Auth0
AUTH0_DOMAIN=yourdomain.auth0.com
AUTH0_CLIENTID=yourclientid
AUTH0_REDIRECT_URI=http://localhost:8080/auth0-landing
# from root folder
npm run init # installs node modules for api & integrations
npm run start # runs the dev serverSeperti yang terlihat dalam file .env, ada beberapa layanan yang Anda perlukan untuk mendaftar untuk menggunakan proyek dalam bentuk saat ini.
Untuk mendapatkan kredensial yang cakap, pertama -tama Anda harus mendaftar untuk akun yang sangat cakap. Setelah Anda memiliki akun yang cakap, Anda dapat pergi ke aplikasi default yang dihasilkan dan mendapatkan kunci API root untuk itu. Ini akan digunakan untuk lingkungan ABLY_API_KEY . Variabel APP_ID Env harus diatur ke bagian pertama dari kunci API Anda, sebelum fullstop. Jika kunci API Anda adalah 12345.jh40fj23jkd0-,32c3-j- , Anda harus mengaturnya ke 12345 .
Untuk CONTROL_KEY , yang digunakan untuk mengendalikan pembuatan tombol API, aplikasi, dan lebih banyak secara program, Anda harus pergi ke token akses sebagai pengguna yang masuk, dan klik 'Buat token akses baru'. Berikan nama, dari dropdown 'Akun' Pilih akun yang memiliki aplikasi yang Anda miliki untuk kunci API, dan pastikan untuk memilih read:key dan write:key . Buat token, dan gunakan nilainya sebagai CONTROL_KEY .
CosmosDB digunakan untuk menyimpan data untuk aplikasi ini. Untuk mendapatkan akun Azure dan membuat sumber daya COSMOSDB, ikuti langkah -langkah dalam tutorial pengaturan Azure. Anda harus mengatur COSMOS_ENDPOINT menjadi URI yang disediakan di subaccount baru Anda. COSMOS_KEY adalah kunci utama untuk akun COSMOSDB, yang dapat Anda akses seperti yang dijelaskan oleh Azure.
COSMOS_DATABASE_ID adalah nama wadah yang akan Anda gunakan di dalam akun CosmosDB Anda.
Menggunakan akun Azure yang sama yang dibuat untuk CosmoSDB, buat wadah penyimpanan data baru. Setelah Anda memiliki pengaturan itu, buka bagian 'Akses Keys' di bilah samping untuk mendapatkan connection string untuk AZURE_STORAGE_CONNECTION_STRING , dan kemudian atur AZURE_STORAGE_CONTAINER_NAME ke apa pun yang Anda beri nama wadah tersebut.
Jika Anda ingin memasukkan AUTH0 sebagai metode otentikasi, Anda perlu membuat akun AUTH0. Setelah Anda memiliki akun AUTH0, buat aplikasi dengan 'aplikasi web reguler' yang dipilih sebagai jenis aplikasi. Di aplikasi itu Anda kemudian dapat menyalin domain untuk AUTH0_DOMAIN , dan clientId untuk AUTH0_CLIENTID . AUTH0_REDIRECT_URI harus menunjuk ke URI yang sesuai bahwa AUTH0, setelah mengautentikasi pengguna, harus diarahkan kembali ke. Nilai default harus berfungsi untuk berjalan secara lokal.
Pada tab Pengaturan aplikasi AUTH0 Anda, gulir ke bawah ke bagian yang disebut 'Aplikasi URI.' Di dalamnya, Anda harus melihat bidang untuk 'URL panggilan balik yang diizinkan' dan 'URL logout yang diizinkan.' Untuk konteks, aliran halaman web menggunakan AUTH0 adalah:
Your site links a user to your Auth0 app's login page, where they sign in The Auth0 page redirects the user back to your website's 'callback' page When the user wants to log out, they are directed to the Auth0 app's logout page and then redirected back to the page specified in the 'returnTo' query passed to the logout page
Untuk menghindari potensi penyalahgunaan dan penyalahgunaan, Anda perlu menentukan URLS AUTH0 apa yang dapat dialihkan. Saat menjadi hosting aplikasi obrolan ini secara lokal, itu di-host di localhost: 8080, jadi atur URL panggilan balik yang diizinkan ke 'http: // localhost: 8080/auth0-landing'. Ketika pengguna keluar, kami akan mengarahkan kembali pengguna ke halaman utama kami, jadi atur URL logout yang diizinkan ke 'http: // localhost: 8080/'.
Aplikasi obrolan terdiri dari yang berikut:
Archive API untuk menerima acara dari reaktor dengan cakap dan mempertahankan riwayat obrolanChat Archive . Aplikasi React adalah aplikasi default, satu halaman. Ini menggunakan campuran react-router-dom dan AppProvider khusus untuk memberikan konteks keamanan untuk aplikasi.
Aplikasi ini menggunakan @ably-labs/react-hooks untuk berinteraksi dengan saluran yang cakap , dan aplikasi ini terdiri dari komponen fungsional reaksi modern.
Snowpack adalah server pengembangan, yang secara transparan akan membangun kode ES6 untuk produksi.
BFF adalah API spesifik aplikasi yang berisi semua logika server untuk aplikasi obrolan. Karena di-host di aplikasi web statis Azure , kami dapat menggunakan azure-functions-core-tools menjalankan server API.
Selain itu, runtime Azure Static Web Apps akan menjadi tuan rumah API untuk kami - jadi kami tidak perlu khawatir tentang mengkonfigurasi hosting. BFF dieksekusi pada infrastrukutre tanpa server, dan Azure SWA akan skala otomatis untuk memenuhi permintaan.
Untuk menambahkan titik akhir API baru, Anda perlu menambahkan direktori baru ke folder api .
Pertama, buat direktori untuk API baru - misalnya, api/messages . Kemudian, buat file function.json di direktori baru.
{
"bindings" : [
{
"route" : " messages " ,
"authLevel" : " function " ,
"type" : " httpTrigger " ,
"direction" : " in " ,
"name" : " req " ,
"methods" : [ " get " , " post " ]
},
{
"type" : " http " ,
"direction" : " out " ,
"name" : " res "
}
],
"scriptFile" : " ../dist/messages/index.js "
} Selanjutnya, Anda harus membuat API TypeScript Anda:
import "../startup" ;
import { Context , HttpRequest } from "@azure/functions" ;
export default async function ( context : Context , req : HttpRequest ) : Promise < void > {
context . res = { status : 200 , body : "I'm an API" } ;
} API ini sekarang akan dipasang di http://localhost:8080/api/messages .
Dan itu saja! Perkakas dan SDK akan mendeteksi kode Anda saat Anda mengubahnya dan membangun kembali fungsi Anda untuk Anda.
Aplikasi ini menggunakan otentikasi token JWT antara aplikasi web dan BFF. Kami menyimpan kredensial pengguna dan asin, kata sandi hash satu arah (dilakukan dengan bcrypt) di database CosmoSDB.
Ketika pengguna mengotentikasi, aplikasi menandatangani token JWT dengan ID dan nama pengguna pengguna yang kemudian dikirim ke BFF dalam permintaan berikutnya untuk data yang diautentikasi. Ini berarti, dengan sejumlah kecil kode di API, kami dapat memastikan bahwa pengguna adalah siapa yang mereka klaim, dan bahwa mereka berhak mengakses data API.
Kami dapat memperluas model ini untuk memasukkan kumpulan roles untuk otentikasi berbasis klaim ke sumber daya dalam aplikasi.
Authenticated User Only Kita dapat membuat panggilan API yang diautentikasi JWT token dengan menggunakan metode kenyamanan berikut di BFF API .
import "../startup" ;
import { Context , HttpRequest } from "@azure/functions" ;
import { authorized , ApiRequestContext } from "../common/ApiRequestContext" ;
export default async function ( context : Context , req : HttpRequest ) : Promise < void > {
await authorized ( context , req , ( ) => {
// This code will only run if the user is authenticated
context . res = {
status : 200 ,
body : JSON . stringify ( "I am validated and authenticated" )
} ;
} ) ;
}Jika Anda ingin mengakses informasi pengguna yang diautentikasi sebagai bagian dari salah satu panggilan API ini, Anda dapat melakukan hal berikut:
import "../startup" ;
import { Context , HttpRequest } from "@azure/functions" ;
import { authorized , ApiRequestContext } from "../common/ApiRequestContext" ;
export default async function ( context : Context , req : HttpRequest ) : Promise < void > {
await authorized (
context ,
req ,
( { user } : ApiRequestContext ) => {
// user is the userDetails object retrieved from CosmosDb
context . res = {
status : 200 ,
body : JSON . stringify ( "I am validated and authenticated" )
} ;
} ,
true
) ; // <- true to include the userDetails object in the ApiRequestContext
} Otentikasi dalam aplikasi diimplementasikan di AppProviders.jsx .
Ini menyediakan kait bereaksi yang akan mengembalikan objek userDetails jika pengguna diautentikasi (bersama dengan memastikan bahwa pengguna diautentikasi sama sekali). Jika pengguna yang diberikan tidak diautentikasi, mereka akan dialihkan ke halaman login dalam semua kasus.
Karena AppProvider menangani otentikasi, Anda harus menggunakan kait untuk mengakses data pengguna, dan untuk membuat panggilan API yang diautentikasi dalam komponen apa pun.
Berikut adalah contoh mengakses objek userDetails dari pengguna yang saat ini diautentikasi.
import { useAuth } from "../../AppProviders" ;
const MyComponent = ( ) => {
const { user } = useAuth ( ) ;
return < div > { user . username } </ div > ;
} ;
export default MyComponent ; Anda juga dapat mengakses instance dari kelas BffApiClient , yang memungkinkan Anda untuk melakukan panggilan API yang diautentikasi dan sudah berisi JWT token pengguna yang saat ini masuk.
import { useAuth } from "../../AppProviders" ;
const MyComponent = ( ) => {
const { api } = useAuth ( ) ;
const [ channels , setChannels ] = useState ( [ ] ) ;
useEffect ( ( ) => {
const fetchChannels = async ( ) => {
const response = await api . listChannels ( ) ;
setChannels ( response . channels ) ;
} ;
fetchChannels ( ) ;
} , [ ] ) ;
return < div > ... bind channel data here </ div > ;
} ;
export default MyComponent ; Contoh di atas menggunakan hook useEffect untuk mengambil saluran ketika komponen dipasang - permintaan API dibuat menggunakan instance api , yang disediakan oleh hook useAuth .
Ini adalah satu -satunya cara Anda harus melakukan panggilan API ke BFF dari komponen, karena akan memastikan token JWT valid dan hadir.
Jika Anda menambahkan BFF APIs baru ke aplikasi, Anda harus menerapkan fungsi baru di /app/src/sdk/BffApiClient.js untuk membuatnya tersedia untuk komponen Anda.
Panggilan BffApiClient ini sederhana, dan terlihat seperti ini:
async listChannels ( ) {
const result = await this . get ( "/api/channels" ) ;
return await result . json ( ) ;
} Beberapa kode utilitas di klien akan memastikan JWT token yang benar hadir saat permintaan dibuat.
Kami menggunakan CosmosDB untuk menyimpan metadata aplikasi kami karena merupakan database yang dapat diskalakan, sangat tersedia, dan dikelola yang tidak harus kami lakukan sendiri. Ini dapat berjalan dalam mode pra-pra-disediakan atau tanpa server, membantu menjaga biaya tetap rendah ketika aplikasi tidak digunakan (dengan biaya beberapa kinerja).
Kami menggunakan basis data COSMOSDB tunggal untuk menyimpan semua metadata, dan di dalamnya, kami telah membuat koleksi untuk setiap jenis entitas yang kami simpan.
Misalnya: Koleksi User , menyimpan catatan pengguna kami - dan dapat ditanyai menggunakan sintaksis seperti SQL. CosmosDB memudahkan ini dengan mengindeks dokumen JSON secara otomatis.
Setiap entitas metadata yang disimpan memiliki id dan bidang type , dan kami menggunakan kelas generic repository ( /api/common/dataaccess/CosmosDbMetadataRepository ) untuk memuat dan menyimpan entitas ini.
Untuk pengembangan lokal, Anda dapat menggunakan versi cloud yang di -host dari COSMOS, atau menggunakan salah satu docker container images yang tersedia untuk menjalankan salinan database lokal.
Kami menggunakan Ably channels untuk menyimpan pesan obrolan kami dan untuk mendorong acara ke aplikasi React kami. Setiap pengguna yang terhubung akan menerima pesan untuk saluran yang mereka lihat secara aktif secara real-time, dan kami menggunakan Channel rewind untuk mengisi pesan yang paling baru dikirim.
Pesan dapat corrected secara asyncron setelah diterima - misalnya, untuk menerapkan penyaringan kata -kata kotor, atau untuk memperbaiki kesalahan ejaan. Pesan koreksi ini akan menjadi bagian dari aliran, dan diterapkan secara surut dalam aplikasi React. (Pengembangan lebih lanjut tentang ini di epos selanjutnya)
Desain ini memungkinkan kami untuk berdiri API tambahan yang mengkonsumsi acara ini, dan menerbitkan elaborasi mereka sendiri di saluran untuk ditanggapi klien.
Karena peristiwa yang cakap akan lenyap dari waktu ke waktu, kita akan menyimpan salinan acara masuk di setiap saluran ke Chat Archive kita melalui Archive API .
Archive API akan menerima pesan reaktor untuk semua saluran kami, dan menambahkannya ke Azure Storage Blobs khusus saluran. API akan ditambahkan ke satu file sampai mencapai ambang ukuran (~ 500kb) dan kemudian membuat file baru untuk pesan berikutnya.
Archive API akan memelihara catatan file arsip yang saat ini aktif dalam Metadata database untuk setiap saluran.
Archive API akan dapat memperbarui indeks pencarian karena pesan diterima dan diarsipkan untuk mengeksposnya nanti dalam pencarian.
Tes ditulis dengan jest dengan ts-jest yang digunakan untuk menjalankan tes TypeScript API.