1. Nội dung bạn sẽ tạo
Trong lớp học lập trình này, bạn sẽ xây dựng một blog du lịch có bản đồ cộng tác theo thời gian thực sử dụng tính năng mới nhất trong thư viện Angular của chúng tôi: AngularFire. Ứng dụng web hoàn thiện sẽ có một blog du lịch, nơi bạn có thể tải hình ảnh lên từng địa điểm mà bạn đã đến.
AngularFire sẽ được dùng để xây dựng ứng dụng web, Bộ mô phỏng để kiểm thử cục bộ, Xác thực để theo dõi dữ liệu người dùng, Firestore và Storage để lưu trữ dữ liệu và nội dung nghe nhìn, được hỗ trợ bởi Cloud Functions và cuối cùng là tính năng Lưu trữ Firebase để triển khai ứng dụng.
Kiến thức bạn sẽ học được
- Cách phát triển cục bộ bằng các sản phẩm của Firebase bằng Bộ mô phỏng
- Cách cải thiện ứng dụng web bằng AngularFire
- Cách duy trì dữ liệu trong Firestore
- Cách lưu trữ nội dung nghe nhìn trong Bộ nhớ
- Cách triển khai ứng dụng của bạn cho tính năng Lưu trữ Firebase
- Cách sử dụng Cloud Functions để tương tác với cơ sở dữ liệu và API
Bạn cần có
- Node.js phiên bản 10 trở lên
- Tài khoản Google để tạo và quản lý Dự án Firebase của bạn
- Firebase CLI phiên bản 11.14.2 trở lên
- Một trình duyệt mà bạn chọn, chẳng hạn như Chrome
- Hiểu biết cơ bản về Angular và JavaScript
2. Nhận mã mẫu
Sao chép kho lưu trữ GitHub của lớp học lập trình từ dòng lệnh:
git clone https://github.com/firebase/codelab-friendlychat-web
Ngoài ra, nếu chưa cài đặt git, bạn có thể tải kho lưu trữ xuống dưới dạng tệp ZIP.
Kho lưu trữ GitHub chứa các dự án mẫu dành cho nhiều nền tảng.
Lớp học lập trình này chỉ sử dụng kho lưu trữ webframework:
- 📁 webframework: Mã khởi đầu mà bạn sẽ xây dựng trong lớp học lập trình này.
Cài đặt phần phụ thuộc
Sau khi sao chép, hãy cài đặt các phần phụ thuộc trong thư mục gốc và thư mục functions
trước khi tạo ứng dụng web.
cd webframework && npm install
cd functions && npm install
Cài đặt Firebase CLI
Cài đặt Firebase CLI bằng lệnh sau trong thiết bị đầu cuối:
npm install -g firebase-tools
Kiểm tra kỹ để đảm bảo phiên bản Firebase CLI của bạn lớn hơn 11.14.2 bằng cách sử dụng:
firebase --version
Nếu phiên bản của bạn thấp hơn 11.14.2, vui lòng cập nhật bằng:
npm update firebase-tools
3. Tạo và thiết lập dự án Firebase
Tạo dự án Firebase
- Đăng nhập vào Firebase.
- Trong bảng điều khiển của Firebase, hãy nhấp vào Thêm dự án, sau đó đặt tên cho dự án Firebase của bạn là <your-project>. Ghi nhớ mã dự án cho dự án Firebase của bạn.
- Nhấp vào Create Project (Tạo dự án).
Lưu ý quan trọng: Dự án Firebase của bạn sẽ có tên là <your-project>, nhưng Firebase sẽ tự động chỉ định cho dự án đó một Mã dự án duy nhất ở dạng <your-project>-1234. Giá trị nhận dạng duy nhất này là cách dự án của bạn thực sự được xác định (kể cả trong CLI), trong khi <your-project> chỉ là tên hiển thị.
Ứng dụng mà chúng ta sắp xây dựng sử dụng các sản phẩm của Firebase có sẵn cho các ứng dụng web:
- Xác thực Firebase để dễ dàng cho phép người dùng đăng nhập vào ứng dụng của bạn.
- Cloud Firestore để lưu dữ liệu có cấu trúc lên đám mây và nhận thông báo tức thì khi dữ liệu thay đổi.
- Cloud Storage cho Firebase để lưu tệp trên đám mây.
- Lưu trữ Firebase để lưu trữ và phân phát tài sản của bạn.
- Các hàm để tương tác với API nội bộ và API bên ngoài.
Một số sản phẩm trong số này cần cấu hình đặc biệt hoặc cần được bật bằng cách sử dụng bảng điều khiển của Firebase.
Thêm ứng dụng web Firebase vào dự án
- Nhấp vào biểu tượng web để tạo ứng dụng web Firebase mới.
- Ở bước tiếp theo, bạn sẽ thấy một đối tượng cấu hình. Sao chép nội dung của đối tượng này vào tệp
environments/environment.ts
.
Bật tính năng đăng nhập cho tính năng Xác thực Firebase của Google
Để cho phép người dùng đăng nhập vào ứng dụng web bằng Tài khoản Google của họ, chúng tôi sẽ sử dụng phương thức đăng nhập là Google.
Cách bật tính năng đăng nhập bằng Google:
- Trong bảng điều khiển của Firebase, hãy tìm mục Build (Tạo) trên bảng điều khiển bên trái.
- Nhấp vào Xác thực, sau đó nhấp vào thẻ Phương thức đăng nhập (hoặc nhấp vào đây để chuyển thẳng đến đó).
- Bật nhà cung cấp dịch vụ đăng nhập Google, sau đó nhấp vào Save (Lưu).
- Đặt tên công khai của ứng dụng là <your-project-name> rồi chọn Email hỗ trợ dự án từ trình đơn thả xuống.
Bật Cloud Firestore
- Trong phần Build (Tạo) trên bảng điều khiển của Firebase, hãy nhấp vào Firestore Database (Cơ sở dữ liệu khôi phục).
- Nhấp vào Create Database (Tạo cơ sở dữ liệu) trong ngăn Cloud Firestore.
- Thiết lập vị trí lưu trữ dữ liệu của bạn trên Cloud Firestore. Bạn có thể để cài đặt này là mặc định hoặc chọn một khu vực gần bạn.
Bật Cloud Storage
Ứng dụng web sử dụng Cloud Storage cho Firebase để lưu trữ, tải lên và chia sẻ hình ảnh.
- Trong phần Build (Tạo) của bảng điều khiển của Firebase, hãy nhấp vào Storage (Bộ nhớ).
- Nếu không có nút Bắt đầu, thì điều đó có nghĩa là Cloud Storage đã
bật lên, và bạn không cần làm theo các bước bên dưới.
- Nhấp vào Bắt đầu.
- Đọc tuyên bố từ chối trách nhiệm về các quy tắc bảo mật cho dự án Firebase của bạn, rồi nhấp vào Tiếp theo.
- Vị trí trong Cloud Storage được chọn sẵn cùng với khu vực mà bạn đã chọn cho cơ sở dữ liệu Cloud Firestore của mình. Nhấp vào Xong để hoàn tất quá trình thiết lập.
Với quy tắc bảo mật mặc định, bất kỳ người dùng đã xác thực nào cũng có thể ghi mọi nội dung vào Cloud Storage. Chúng ta sẽ tăng cường bảo mật cho bộ nhớ sau trong lớp học lập trình này.
4. Kết nối với dự án Firebase của bạn
Giao diện dòng lệnh (CLI) Firebase cho phép bạn sử dụng tính năng Lưu trữ Firebase để phân phát ứng dụng web cục bộ, cũng như triển khai ứng dụng web cho dự án Firebase của bạn.
Đảm bảo dòng lệnh của bạn đang truy cập vào thư mục webframework
cục bộ của ứng dụng.
Kết nối mã ứng dụng web với dự án Firebase của bạn. Trước tiên, hãy đăng nhập vào Firebase CLI trong dòng lệnh:
firebase login
Tiếp theo, hãy chạy lệnh sau để tạo một email đại diện cho dự án. Thay thế $YOUR_PROJECT_ID
bằng mã dự án Firebase của bạn.
firebase use $YOUR_PROJECT_ID
Thêm AngularFire
Để thêm AngularFire vào ứng dụng, hãy chạy lệnh:
ng add @angular/fire
Sau đó, làm theo hướng dẫn dòng lệnh rồi chọn các tính năng có trong dự án Firebase của bạn.
Chạy Firebase
Để khởi chạy dự án Firebase, hãy chạy:
firebase init
Sau đó, làm theo lời nhắc dòng lệnh, hãy chọn các tính năng và trình mô phỏng được dùng trong dự án Firebase của bạn.
Khởi động trình mô phỏng
Từ thư mục webframework
, hãy chạy lệnh sau để khởi động trình mô phỏng:
firebase emulators:start
Cuối cùng, bạn sẽ thấy như sau:
$ firebase emulators:start
i emulators: Starting emulators: auth, functions, firestore, hosting, functions
i firestore: Firestore Emulator logging to firestore-debug.log
i hosting: Serving hosting files from: public
✔ hosting: Local server: http://localhost:5000
i ui: Emulator UI logging to ui-debug.log
i functions: Watching "/functions" for Cloud Functions...
✔ functions[updateMap]: firestore function initialized.
┌─────────────────────────────────────────────────────────────┐
│ ✔ All emulators ready! It is now safe to connect your app. │
│ i View Emulator UI at http://localhost:4000 │
└─────────────────────────────────────────────────────────────┘
┌────────────────┬────────────────┬─────────────────────────────────┐
│ Emulator │ Host:Port │ View in Emulator UI │
├────────────────┼────────────────┼─────────────────────────────────┤
│ Authentication │ localhost:9099 │ http://localhost:4000/auth │
├────────────────┼────────────────┼─────────────────────────────────┤
│ Functions │ localhost:5001 │ http://localhost:4000/functions │
├────────────────┼────────────────┼─────────────────────────────────┤
│ Firestore │ localhost:8080 │ http://localhost:4000/firestore │
├────────────────┼────────────────┼─────────────────────────────────┤
│ Hosting │ localhost:5000 │ n/a │
└────────────────┴────────────────┴─────────────────────────────────┘
Emulator Hub running at localhost:4400
Other reserved ports: 4500
Issues? Report them at https://github.com/firebase/firebase-tools/issues and attach the *-debug.log files.
Sau khi bạn thấy thông báo ✔All emulators ready!
, tức là trình mô phỏng đã sẵn sàng để sử dụng.
Bạn sẽ thấy giao diện người dùng của ứng dụng du lịch. Giao diện người dùng này (chưa) hoạt động:
Giờ hãy bắt đầu xây dựng!
5. Kết nối ứng dụng web với trình mô phỏng
Dựa trên bảng trong nhật ký của trình mô phỏng, trình mô phỏng Cloud Firestore đang nghe trên cổng 8080 và trình mô phỏng xác thực đang nghe trên cổng 9099.
Mở EmulatorUI
Trong trình duyệt web, hãy chuyển đến http://127.0.0.1:4000/. Bạn sẽ thấy giao diện người dùng của Bộ mô phỏng.
Định tuyến ứng dụng để dùng trình mô phỏng
Trong src/app/app.module.ts
, hãy thêm mã sau vào danh sách nhập của AppModule
:
@NgModule({
declarations: [...],
imports: [
provideFirebaseApp(() => initializeApp(environment.firebase)),
provideAuth(() => {
const auth = getAuth();
if (location.hostname === 'localhost') {
connectAuthEmulator(auth, 'http://127.0.0.1:9099', { disableWarnings: true });
}
return auth;
}),
provideFirestore(() => {
const firestore = getFirestore();
if (location.hostname === 'localhost') {
connectFirestoreEmulator(firestore, '127.0.0.1', 8080);
}
return firestore;
}),
provideFunctions(() => {
const functions = getFunctions();
if (location.hostname === 'localhost') {
connectFunctionsEmulator(functions, '127.0.0.1', 5001);
}
return functions;
}),
provideStorage(() => {
const storage = getStorage();
if (location.hostname === 'localhost') {
connectStorageEmulator(storage, '127.0.0.1', 5001);
}
return storage;
}),
...
]
Ứng dụng hiện được định cấu hình để sử dụng trình mô phỏng cục bộ, cho phép thực hiện kiểm thử và phát triển trên máy.
6. Đang thêm phương thức xác thực
Giờ đây, trình mô phỏng đã được thiết lập cho ứng dụng, chúng ta có thể thêm các tính năng Xác thực để đảm bảo từng người dùng đều đăng nhập trước khi đăng thông báo.
Để thực hiện việc này, chúng ta có thể nhập các hàm signin
trực tiếp từ AngularFire và theo dõi trạng thái xác thực của người dùng bằng hàm authState
. Sửa đổi các hàm của trang đăng nhập để trang kiểm tra trạng thái xác thực của người dùng khi tải.
Chèn tính năng xác thực AngularFire
Trong src/app/pages/login-page/login-page.component.ts
, hãy nhập Auth
từ @angular/fire/auth
rồi chèn vào LoginPageComponent
. Các nhà cung cấp dịch vụ xác thực (như Google) và các hàm như signin
, signout
cũng có thể được nhập trực tiếp từ cùng một gói và được sử dụng trong ứng dụng.
import { Auth, GoogleAuthProvider, signInWithPopup, signOut, user } from '@angular/fire/auth';
export class LoginPageComponent implements OnInit {
private auth: Auth = inject(Auth);
private provider = new GoogleAuthProvider();
user$ = user(this.auth);
constructor() {}
ngOnInit(): void {}
login() {
signInWithPopup(this.auth, this.provider).then((result) => {
const credential = GoogleAuthProvider.credentialFromResult(result);
return credential;
})
}
logout() {
signOut(this.auth).then(() => {
console.log('signed out');}).catch((error) => {
console.log('sign out error: ' + error);
})
}
}
Bây giờ, trang đăng nhập đã hoạt động! Hãy thử đăng nhập và xem kết quả trong Trình mô phỏng xác thực.
7. Định cấu hình Firestore
Ở bước này, bạn sẽ thêm chức năng đăng và cập nhật các bài đăng trên blog du lịch được lưu trữ trong Firestore.
Tương tự như Xác thực, các hàm Firestore được đóng gói sẵn từ AngularFire. Mỗi tài liệu thuộc một tập hợp và mỗi tài liệu cũng có thể chứa các tập hợp lồng nhau. Bạn phải biết path
của tài liệu trong Firestore để tạo và cập nhật một bài đăng trên blog du lịch.
Triển khai TravelService
Vì nhiều trang khác nhau sẽ cần đọc và cập nhật tài liệu trên Firestore trong ứng dụng web, nên chúng ta có thể triển khai các hàm này trong src/app/services/travel.service.ts
để tránh việc chèn cùng một hàm AngularFire nhiều lần vào mỗi trang.
Bắt đầu bằng việc chèn Auth
, tương tự như bước trước, cũng như Firestore
vào dịch vụ của chúng ta. Việc xác định một đối tượng user$
có thể quan sát để theo dõi trạng thái xác thực hiện tại cũng rất hữu ích.
import { doc, docData, DocumentReference, Firestore, getDoc, setDoc, updateDoc, collection, addDoc, deleteDoc, collectionData, Timestamp } from "@angular/fire/firestore";
export class TravelService {
firestore: Firestore = inject(Firestore);
auth: Auth = inject(Auth);
user$ = authState(this.auth).pipe(filter(user => user !== null), map(user => user!));
router: Router = inject(Router);
Thêm một bài đăng du lịch
Các bài đăng du lịch sẽ tồn tại dưới dạng tài liệu được lưu trữ trong Firestore và vì tài liệu phải tồn tại trong các bộ sưu tập, nên bộ sưu tập chứa tất cả các bài đăng du lịch sẽ được đặt tên là travels
. Do đó, đường dẫn của mọi bài đăng du lịch sẽ là travels/
Bằng cách sử dụng hàm addDoc
từ AngularFire, bạn có thể chèn một đối tượng vào một tập hợp:
async addEmptyTravel(userId: String) {
...
addDoc(collection(this.firestore, 'travels'), travelData).then((travelRef) => {
collection(this.firestore, `travels/${travelRef.id}/stops`);
setDoc(travelRef, {... travelData, id: travelRef.id})
this.router.navigate(['edit', `${travelRef.id}`]);
return travelRef;
})
}
Cập nhật và xoá dữ liệu
Dựa trên uid của bất kỳ bài đăng du lịch nào, bạn có thể suy ra đường dẫn của tài liệu được lưu trữ trong Firestore. Sau đó, bạn có thể đọc, cập nhật hoặc xoá đường dẫn này bằng các hàm updateFoc
và deleteDoc
của AngularFire:
async updateData(path: string, data: Partial<Travel | Stop>) {
await updateDoc(doc(this.firestore, path), data)
}
async deleteData(path: string) {
const ref = doc(this.firestore, path);
await deleteDoc(ref)
}
Đọc dữ liệu dưới dạng đối tượng có thể quan sát
Vì các bài đăng du lịch và điểm dừng trên đường đi có thể được sửa đổi sau khi tạo, nên sẽ hữu ích hơn nếu nhận các đối tượng tài liệu dưới dạng đối tượng có thể quan sát, để đăng ký mọi thay đổi được thực hiện. Chức năng này do các hàm docData
và collectionData
của @angular/fire/firestore
cung cấp.
getDocData(path: string) {
return docData(doc(this.firestore, path), {idField: 'id'}) as Observable<Travel | Stop>
}
getCollectionData(path: string) {
return collectionData(collection(this.firestore, path), {idField: 'id'}) as Observable<Travel[] | Stop[]>
}
Thêm trạm dừng vào bài đăng du lịch
Bây giờ, các hoạt động của bưu điện du lịch đã được thiết lập, đã đến lúc xem xét các điểm dừng. Các điểm dừng này sẽ nằm trong một tập hợp con của một bưu điện du lịch như vậy: travels/
Việc này gần giống với việc tạo một bài đăng về du lịch. Vì vậy, hãy thử thách bản thân tự triển khai bài đăng này hoặc xem cách triển khai dưới đây:
async addStop(travelId: string) {
...
const ref = await addDoc(collection(this.firestore, `travels/${travelId}/stops`), stopData)
setDoc(ref, {...stopData, id: ref.id})
}
Hay quá! Các hàm Firestore đã được triển khai trong dịch vụ Du lịch, nên giờ đây bạn có thể thấy các hàm này trong thực tế.
Sử dụng các hàm Firestore trong ứng dụng
Chuyển đến src/app/pages/my-travels/my-travels.component.ts
rồi chèn TravelService
để sử dụng các hàm.
travelService = inject(TravelService);
travelsData$: Observable<Travel[]>;
stopsList$!: Observable<Stop[]>;
constructor() {
this.travelsData$ = this.travelService.getCollectionData(`travels`) as Observable<Travel[]>
}
TravelService
được gọi trong hàm khởi tạo để lấy một mảng Có thể quan sát cho tất cả các hành trình.
Trong trường hợp chỉ cần di chuyển của người dùng hiện tại, hãy sử dụng hàm query
.
Các phương pháp khác để đảm bảo bảo mật bao gồm triển khai các quy tắc bảo mật hoặc sử dụng Cloud Functions với Firestore như được trình bày trong các bước không bắt buộc dưới đây
Sau đó, bạn chỉ cần gọi các hàm được triển khai trong TravelService
.
async createTravel(userId: String) {
this.travelService.addEmptyTravel(userId);
}
deleteTravel(travelId: String) {
this.travelService.deleteData(`travels/${travelId}`)
}
Bây giờ, trang Du lịch của tôi đã hoạt động bình thường! Hãy xem điều gì xảy ra trong trình mô phỏng Firestore khi bạn tạo một bài đăng mới về du lịch.
Sau đó, lặp lại các hàm cập nhật trong /src/app/pages/edit-travels/edit-travels.component.ts
:
travelService: TravelService = inject(TravelService)
travelId = this.activatedRoute.snapshot.paramMap.get('travelId');
travelData$: Observable<Travel>;
stopsData$: Observable<Stop[]>;
constructor() {
this.travelData$ = this.travelService.getDocData(`travels/${this.travelId}`) as Observable<Travel>
this.stopsData$ = this.travelService.getCollectionData(`travels/${this.travelId}/stops`) as Observable<Stop[]>
}
updateCurrentTravel(travel: Partial<Travel>) {
this.travelService.updateData(`travels${this.travelId}`, travel)
}
updateCurrentStop(stop: Partial<Stop>) {
stop.type = stop.type?.toString();
this.travelService.updateData(`travels${this.travelId}/stops/${stop.id}`, stop)
}
addStop() {
if (!this.travelId) return;
this.travelService.addStop(this.travelId);
}
deleteStop(stopId: string) {
if (!this.travelId || !stopId) {
return;
}
this.travelService.deleteData(`travels${this.travelId}/stops/${stopId}`)
this.stopsData$ = this.travelService.getCollectionData(`travels${this.travelId}/stops`) as Observable<Stop[]>
}
8. Định cấu hình bộ nhớ
Bây giờ, bạn sẽ triển khai Bộ nhớ để lưu trữ hình ảnh và các loại nội dung nghe nhìn khác.
Cloud Firestore là giải pháp phù hợp nhất để lưu trữ dữ liệu có cấu trúc, chẳng hạn như đối tượng JSON. Cloud Storage được thiết kế để lưu trữ các tệp hoặc blob. Trong ứng dụng này, bạn sẽ dùng thông tin đó để cho phép người dùng chia sẻ ảnh du lịch của họ.
Tương tự như vậy với Firestore, việc lưu trữ và cập nhật tệp bằng Bộ nhớ yêu cầu một giá trị nhận dạng duy nhất cho mỗi tệp.
Hãy triển khai các hàm trong TraveService
:
Tải tệp lên
Chuyển đến src/app/services/travel.service.ts
rồi chèn Bộ nhớ từ AngularFire:
export class TravelService {
firestore: Firestore = inject(Firestore);
auth: Auth = inject(Auth);
storage: Storage = inject(Storage);
Và triển khai chức năng tải lên:
async uploadToStorage(path: string, input: HTMLInputElement, contentType: any) {
if (!input.files) return null
const files: FileList = input.files;
for (let i = 0; i < files.length; i++) {
const file = files.item(i);
if (file) {
const imagePath = `${path}/${file.name}`
const storageRef = ref(this.storage, imagePath);
await uploadBytesResumable(storageRef, file, contentType);
return await getDownloadURL(storageRef);
}
}
return null;
}
Điểm khác biệt chính giữa việc truy cập vào tài liệu qua Firestore và các tệp trên Cloud Storage là mặc dù cả hai đều đi theo đường dẫn có cấu trúc thư mục, nhưng tổ hợp URL cơ sở và đường dẫn sẽ được lấy thông qua getDownloadURL
, sau đó có thể được lưu trữ và sử dụng trong tệp .
Dùng hàm này trong ứng dụng
Chuyển đến src/app/components/edit-stop/edit-stop.component.ts
rồi gọi hàm tải lên bằng:
async uploadFile(file: HTMLInputElement, stop: Partial<Stop>) {
const path = `/travels/${this.travelId}/stops/${stop.id}`
const url = await this.travelService.uploadToStorage(path, file, {contentType: 'image/png'});
stop.image = url ? url : '';
this.travelService.updateData(path, stop);
}
Khi hình ảnh được tải lên, tệp đa phương tiện sẽ được tải lên bộ nhớ và URL được lưu trữ tương ứng trong tài liệu trên Firestore.
9. Triển khai ứng dụng
Bây giờ, chúng ta đã sẵn sàng triển khai ứng dụng!
Sao chép các cấu hình firebase
từ src/environments/environment.ts
sang src/environments/environment.prod.ts
rồi chạy:
firebase deploy
Bạn sẽ thấy như sau:
✔ Browser application bundle generation complete.
✔ Copying assets complete.
✔ Index html generation complete.
=== Deploying to 'friendly-travels-b6a4b'...
i deploying storage, firestore, hosting
i firebase.storage: checking storage.rules for compilation errors...
✔ firebase.storage: rules file storage.rules compiled successfully
i firestore: reading indexes from firestore.indexes.json...
i cloud.firestore: checking firestore.rules for compilation errors...
✔ cloud.firestore: rules file firestore.rules compiled successfully
i storage: latest version of storage.rules already up to date, skipping upload...
i firestore: deploying indexes...
i firestore: latest version of firestore.rules already up to date, skipping upload...
✔ firestore: deployed indexes in firestore.indexes.json successfully for (default) database
i hosting[friendly-travels-b6a4b]: beginning deploy...
i hosting[friendly-travels-b6a4b]: found 6 files in .firebase/friendly-travels-b6a4b/hosting
✔ hosting[friendly-travels-b6a4b]: file upload complete
✔ storage: released rules storage.rules to firebase.storage
✔ firestore: released rules firestore.rules to cloud.firestore
i hosting[friendly-travels-b6a4b]: finalizing version...
✔ hosting[friendly-travels-b6a4b]: version finalized
i hosting[friendly-travels-b6a4b]: releasing new version...
✔ hosting[friendly-travels-b6a4b]: release complete
✔ Deploy complete!
Project Console: https://console.firebase.google.com/project/friendly-travels-b6a4b/overview
Hosting URL: https://friendly-travels-b6a4b.web.app
10. Xin chúc mừng!
Bây giờ, ứng dụng của bạn đã được hoàn tất và được triển khai trong Lưu trữ Firebase! Giờ đây, bạn có thể truy cập vào tất cả dữ liệu và số liệu phân tích trong Bảng điều khiển của Firebase.
Để biết thêm các tính năng liên quan đến AngularFire, Hàm, quy tắc bảo mật, đừng quên xem các bước không bắt buộc bên dưới, cũng như các Lớp học lập trình về Firebase khác!
11. Không bắt buộc: Trình bảo vệ xác thực AngularFire
Cùng với tính năng Xác thực Firebase, AngularFire cũng cung cấp các biện pháp bảo vệ dựa trên xác thực trên các tuyến đường để những người dùng không có đủ quyền truy cập có thể được chuyển hướng. Điều này giúp bảo vệ ứng dụng khỏi việc người dùng truy cập vào dữ liệu được bảo vệ.
Trong src/app/app-routing.module.ts
, hãy nhập
import {AuthGuard, redirectLoggedInTo, redirectUnauthorizedTo} from '@angular/fire/auth-guard'
Sau đó, bạn có thể xác định các hàm như thời điểm và nơi người dùng nên được chuyển hướng đến trên một số trang nhất định:
const redirectUnauthorizedToLogin = () => redirectUnauthorizedTo(['signin']);
const redirectLoggedInToTravels = () => redirectLoggedInTo(['my-travels']);
Sau đó, chỉ cần thêm chúng vào tuyến đường của bạn:
const routes: Routes = [
{path: '', component: LoginPageComponent, canActivate: [AuthGuard], data: {authGuardPipe: redirectLoggedInToTravels}},
{path: 'signin', component: LoginPageComponent, canActivate: [AuthGuard], data: {authGuardPipe: redirectLoggedInToTravels}},
{path: 'my-travels', component: MyTravelsComponent, canActivate: [AuthGuard], data: {authGuardPipe: redirectUnauthorizedToLogin}},
{path: 'edit/:travelId', component: EditTravelsComponent, canActivate: [AuthGuard], data: {authGuardPipe: redirectUnauthorizedToLogin}},
];
12. Không bắt buộc: quy tắc bảo mật
Cả Firestore và Cloud Storage đều sử dụng các quy tắc bảo mật (tương ứng là firestore.rules
và security.rules
) để thực thi khả năng bảo mật và xác thực dữ liệu.
Hiện tại, dữ liệu Firestore và Storage có quyền truy cập mở để đọc và ghi, nhưng bạn không muốn mọi người tự mình thay đổi bài đăng! Bạn có thể sử dụng các quy tắc bảo mật để hạn chế quyền truy cập vào bộ sưu tập và tài liệu của mình.
Quy tắc của Firestore
Để chỉ cho phép người dùng đã xác thực xem các bài đăng về du lịch, hãy chuyển đến tệp firestore.rules
rồi thêm:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/travels {
allow read: if request.auth.uid != null;
allow write:
if request.auth.uid == request.resource.data.userId;
}
}
Quy tắc bảo mật cũng có thể dùng để xác thực dữ liệu:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/posts {
allow read: if request.auth.uid != null;
allow write:
if request.auth.uid == request.resource.data.userId;
&& "author" in request.resource.data
&& "text" in request.resource.data
&& "timestamp" in request.resource.data;
}
}
Quy tắc lưu trữ
Tương tự, chúng ta có thể sử dụng các quy tắc bảo mật để thực thi quyền truy cập vào cơ sở dữ liệu lưu trữ trong storage.rules
. Xin lưu ý rằng chúng ta cũng có thể dùng các hàm cho những quy trình kiểm tra phức tạp hơn:
rules_version = '2';
function isImageBelowMaxSize(maxSizeMB) {
return request.resource.size < maxSizeMB * 1024 * 1024
&& request.resource.contentType.matches('image/.*');
}
service firebase.storage {
match /b/{bucket}/o {
match /{userId}/{postId}/{filename} {
allow write: if request.auth != null
&& request.auth.uid == userId && isImageBelowMaxSize(5);
allow read;
}
}
}