Firebase Angular Web Frameworks Codelab

1. آنچه ایجاد خواهید کرد

در این نرم‌افزار، شما یک وبلاگ مسافرتی با یک نقشه مشارکتی بلادرنگ با جدیدترین‌های کتابخانه Angular ما ایجاد می‌کنید: AngularFire . آخرین برنامه وب شامل یک وبلاگ سفر است که در آن می توانید تصاویر را در هر مکانی که به آن سفر کرده اید آپلود کنید.

AngularFire برای ساخت برنامه وب، Emulator Suite برای آزمایش محلی، احراز هویت برای پیگیری داده‌های کاربر، Firestore و Storage برای ماندگاری داده‌ها و رسانه‌ها که توسط Cloud Functions ارائه می‌شود، و در نهایت از Firebase Hosting برای استقرار برنامه استفاده می‌شود.

چیزی که یاد خواهید گرفت

  • نحوه توسعه با محصولات Firebase به صورت محلی با Emulator Suite
  • چگونه برنامه وب خود را با AngularFire تقویت کنید
  • چگونه داده های خود را در Firestore حفظ کنید
  • نحوه ماندگاری رسانه در استوریج
  • نحوه استقرار برنامه خود در میزبانی Firebase
  • نحوه استفاده از توابع ابری برای تعامل با پایگاه های داده و API های خود

آنچه شما نیاز دارید

  • Node.js نسخه 10 یا بالاتر
  • یک حساب Google برای ایجاد و مدیریت پروژه Firebase شما
  • Firebase CLI نسخه 11.14.2 یا بالاتر
  • مرورگر دلخواه شما، مانند کروم
  • درک اولیه Angular و Javascript

2. کد نمونه را دریافت کنید

مخزن GitHub کد لبه را از خط فرمان کلون کنید:

git clone https://github.com/firebase/codelab-friendlychat-web

همچنین، اگر git را نصب نکرده‌اید، می‌توانید مخزن را به عنوان یک فایل ZIP دانلود کنید .

مخزن Github شامل پروژه های نمونه برای چندین پلتفرم است.

این کد لبه فقط از مخزن webframework استفاده می کند:

  • 📁 webframework : کد شروعی که در طول این Codelab بر روی آن ایجاد خواهید کرد.

وابستگی ها را نصب کنید

پس از کلونینگ، قبل از ساخت برنامه وب، وابستگی ها را در پوشه root و functions نصب کنید.

cd webframework && npm install
cd functions && npm install

Firebase CLI را نصب کنید

Firebase CLI را با استفاده از این دستور در ترمینال نصب کنید:

npm install -g firebase-tools

بررسی کنید که نسخه Firebase CLI شما بزرگتر از 11.14.2 باشد با استفاده از:

firebase  --version

اگر نسخه شما کمتر از 11.14.2 است، لطفاً با استفاده از:

npm update firebase-tools

3. یک پروژه Firebase ایجاد و راه اندازی کنید

یک پروژه Firebase ایجاد کنید

  1. وارد Firebase شوید.
  2. در کنسول Firebase، روی Add Project کلیک کنید و سپس نام پروژه Firebase خود را <your-project> بگذارید. شناسه پروژه برای پروژه Firebase خود را به خاطر بسپارید.
  3. روی ایجاد پروژه کلیک کنید.

مهم : پروژه Firebase شما <your-project> نامیده می شود، اما Firebase به طور خودکار یک ID پروژه منحصر به فرد به شکل <your-project>-1234 به آن اختصاص می دهد. این شناسه منحصر به فرد نحوه شناسایی پروژه شما (از جمله در CLI) است، در حالی که <Your-project> صرفاً یک نام نمایشی است.

برنامه‌ای که می‌خواهیم بسازیم از محصولات Firebase استفاده می‌کند که برای برنامه‌های وب در دسترس هستند:

  • Firebase Authentication به کاربران شما اجازه می دهد تا به راحتی وارد برنامه شما شوند.
  • Cloud Firestore برای ذخیره داده‌های ساخت‌یافته در فضای ابری و دریافت اطلاع‌رسانی فوری هنگام تغییر داده‌ها.
  • Cloud Storage برای Firebase برای ذخیره فایل‌ها در فضای ابری.
  • میزبانی Firebase برای میزبانی و خدمات رسانی به دارایی های شما.
  • عملکردهایی برای تعامل با APIهای داخلی و خارجی.

برخی از این محصولات نیاز به تنظیمات خاصی دارند یا باید با استفاده از کنسول Firebase فعال شوند.

یک برنامه وب Firebase را به پروژه اضافه کنید

  1. برای ایجاد یک برنامه وب Firebase جدید، روی نماد وب کلیک کنید.
  2. در مرحله بعد، یک شی پیکربندی را مشاهده خواهید کرد. محتویات این شی را در فایل environments/environment.ts کپی کنید.

ورود به سیستم Google را برای احراز هویت Firebase فعال کنید

برای اینکه به کاربران اجازه دهیم با حساب‌های Google خود وارد برنامه وب شوند، از روش ورود به سیستم Google استفاده می‌کنیم.

برای فعال کردن ورود به سیستم Google :

  1. در کنسول Firebase، قسمت Build را در پانل سمت چپ قرار دهید.
  2. روی تأیید هویت کلیک کنید، سپس روی برگه روش ورود به سیستم کلیک کنید (یا برای رفتن مستقیم به آنجا اینجا را کلیک کنید ).
  3. ارائه دهنده ورود به سیستم Google را فعال کنید، سپس روی ذخیره کلیک کنید.
  4. نام عمومی برنامه خود را روی <your-project-name> تنظیم کنید و یک ایمیل پشتیبانی پروژه را از منوی کشویی انتخاب کنید.

Cloud Firestore را فعال کنید

  1. در بخش ساخت کنسول Firebase، روی Firestore Database کلیک کنید.
  2. روی ایجاد پایگاه داده در پنجره Cloud Firestore کلیک کنید.
  3. مکان ذخیره داده های Cloud Firestore خود را تنظیم کنید. می توانید این را به عنوان پیش فرض بگذارید یا منطقه ای نزدیک به خود انتخاب کنید.

Cloud Storage را فعال کنید

برنامه وب از Cloud Storage برای Firebase برای ذخیره، آپلود و اشتراک گذاری تصاویر استفاده می کند.

  1. در بخش ساخت کنسول Firebase، روی Storage کلیک کنید.
  2. اگر دکمه شروع کار وجود نداشته باشد، به این معنی است که فضای ذخیره سازی ابری از قبل وجود دارد

فعال است و نیازی نیست مراحل زیر را دنبال کنید.

  1. روی Get Started کلیک کنید.
  2. سلب مسئولیت مربوط به قوانین امنیتی پروژه Firebase خود را بخوانید، سپس روی Next کلیک کنید.
  3. مکان Cloud Storage با همان منطقه ای که برای پایگاه داده Cloud Firestore خود انتخاب کرده اید از پیش انتخاب شده است. برای تکمیل تنظیمات روی Done کلیک کنید.

با قوانین امنیتی پیش‌فرض، هر کاربر احراز هویت شده می‌تواند هر چیزی را در Cloud Storage بنویسد. بعداً در این نسخه کد، فضای ذخیره‌سازی خود را ایمن‌تر خواهیم کرد.

4. به پروژه Firebase خود متصل شوید

رابط خط فرمان Firebase (CLI) به شما امکان می دهد از میزبانی Firebase برای ارائه برنامه وب خود به صورت محلی و همچنین برای استقرار برنامه وب خود در پروژه Firebase خود استفاده کنید.

مطمئن شوید که خط فرمان شما به دایرکتوری webframework محلی برنامه شما دسترسی دارد.

کد برنامه وب را به پروژه Firebase خود وصل کنید. ابتدا وارد Firebase CLI در خط فرمان شوید:

firebase login

سپس دستور زیر را برای ایجاد نام مستعار پروژه اجرا کنید. شناسه پروژه Firebase خود را جایگزین $YOUR_PROJECT_ID کنید.

firebase  use  $YOUR_PROJECT_ID

AngularFire را اضافه کنید

برای افزودن AngularFire به برنامه، دستور زیر را اجرا کنید:

ng add @angular/fire

سپس، دستورالعمل های خط فرمان را دنبال کنید و ویژگی هایی را که در پروژه Firebase شما وجود دارد انتخاب کنید.

Firebase را راه اندازی کنید

برای مقداردهی اولیه پروژه Firebase، اجرا کنید:

firebase init

سپس، با پیروی از خط فرمان، ویژگی‌ها و شبیه‌سازهایی را که در پروژه Firebase استفاده شده‌اند، انتخاب کنید.

شبیه سازها را راه اندازی کنید

از پوشه webframework ، دستور زیر را برای شروع شبیه سازها اجرا کنید:

firebase  emulators:start

در نهایت شما باید چیزی شبیه به این را ببینید:

$  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.

پس از مشاهده ✔All emulators ready! پیام، شبیه سازها آماده استفاده هستند.

باید رابط کاربری برنامه سفر خود را ببینید که (هنوز!) کار نمی کند:

حالا بیایید بسازیم!

5. برنامه وب را به شبیه سازها وصل کنید

بر اساس جدول موجود در گزارش‌های شبیه‌ساز، شبیه‌ساز Cloud Firestore در پورت 8080 گوش می‌دهد و شبیه‌ساز Authentication در پورت 9099 گوش می‌دهد.

EmulatorUI را باز کنید

در مرورگر وب خود، به http://127.0.0.1:4000/ بروید. باید رابط کاربری Emulator Suite را ببینید.

برنامه را برای استفاده از شبیه سازها مسیریابی کنید

در src/app/app.module.ts ، کد زیر را به لیست واردات 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;
		}),
		...
	]

این برنامه اکنون برای استفاده از شبیه سازهای محلی پیکربندی شده است، که اجازه می دهد آزمایش و توسعه به صورت محلی انجام شود.

6. افزودن احراز هویت

اکنون که شبیه‌سازها برای برنامه راه‌اندازی شده‌اند، می‌توانیم ویژگی‌های Authentication را اضافه کنیم تا مطمئن شویم که هر کاربر قبل از ارسال پیام وارد سیستم شده است.

برای انجام این کار، ما می توانیم توابع signin مستقیماً از AngularFire وارد کنیم و وضعیت احراز هویت کاربر شما را با تابع authState ردیابی کنیم. توابع صفحه ورود به سیستم را تغییر دهید تا صفحه وضعیت تأیید هویت کاربر را در بارگذاری بررسی کند.

تزریق AngularFire Auth

در src/app/pages/login-page/login-page.component.ts ، Auth از @angular/fire/auth وارد کنید و آن را به LoginPageComponent تزریق کنید. ارائه‌دهندگان احراز هویت، مانند Google، و عملکردهایی مانند signin ، signout نیز می‌توانند مستقیماً از همان بسته وارد شده و در برنامه استفاده شوند.

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);
		})
	}
}

اکنون صفحه ورود فعال است! سعی کنید وارد سیستم شوید و نتایج را در شبیه ساز احراز هویت بررسی کنید.

7. پیکربندی Firestore

در این مرحله، برای پست کردن و به‌روزرسانی پست‌های وبلاگ سفر ذخیره‌شده در Firestore، قابلیت‌هایی را اضافه می‌کنید.

مشابه با احراز هویت، توابع Firestore از AngularFire بسته بندی شده اند. هر سند متعلق به یک مجموعه است و هر سند می تواند مجموعه های تودرتو نیز داشته باشد. دانستن path سند در Firestor برای ایجاد و به روز رسانی یک پست وبلاگ سفر الزامی است.

پیاده سازی TravelService

از آنجایی که بسیاری از صفحات مختلف نیاز به خواندن و به‌روزرسانی اسناد Firestore در برنامه وب دارند، می‌توانیم توابع را در src/app/services/travel.service.ts پیاده‌سازی کنیم تا از تزریق مکرر توابع AngularFire در هر صفحه خودداری کنیم.

با تزریق Auth ، مشابه مرحله قبل، و همچنین Firestore به سرویس ما شروع کنید. تعریف یک شی user$ قابل مشاهده که به وضعیت احراز هویت فعلی گوش می دهد نیز مفید است.

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);

افزودن پست سفر

پست‌های سفر به‌عنوان اسنادی وجود خواهند داشت که در Firestor ذخیره می‌شوند، و از آنجایی که اسناد باید در مجموعه‌ها وجود داشته باشند، مجموعه‌ای که شامل همه پست‌های سفر است، travels نامیده می‌شود. بنابراین مسیر هر پست مسافرتی travels/

با استفاده از تابع addDoc از AngularFire، یک شی را می توان در یک مجموعه درج کرد:

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;

	})
}

به روز رسانی و حذف داده ها

با توجه به uid هر پست سفر، می توان مسیر سند ذخیره شده در Firestore را استنباط کرد، که سپس می توان آن را با استفاده از توابع updateFoc و deleteDoc 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)
}

خواندن داده ها به عنوان یک قابل مشاهده

از آنجایی که پست‌های سفر و توقف‌ها در طول مسیر را می‌توان پس از ایجاد تغییر داد، دریافت اشیاء سند به‌عنوان موارد مشاهده‌پذیر، برای اشتراک در هر تغییری که ایجاد می‌شود، مفیدتر خواهد بود. این قابلیت توسط توابع docData و collectionData از @angular/fire/firestore ارائه شده است.

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[]>
}

اضافه کردن توقف به یک پست مسافرتی

اکنون که عملیات پست مسافرتی راه‌اندازی شده‌اند، زمان آن است که توقف‌هایی را در نظر بگیرید، که در زیر مجموعه‌ای از پست‌های مسافرتی مانند این وجود خواهند داشت: travels/ /stops/ travels/ /stops/

این تقریباً مشابه ایجاد یک پست مسافرتی است، بنابراین خودتان را به چالش بکشید تا آن را به تنهایی اجرا کنید، یا اجرای زیر را بررسی کنید:

async  addStop(travelId: string) {
	...
	const  ref = await  addDoc(collection(this.firestore, `travels/${travelId}/stops`), stopData)
	setDoc(ref, {...stopData, id:  ref.id})
}

خوب! توابع Firestore در سرویس Travel پیاده سازی شده اند، بنابراین اکنون می توانید آنها را در عمل مشاهده کنید.

استفاده از توابع Firestore در برنامه

به src/app/pages/my-travels/my-travels.component.ts بروید و TravelService برای استفاده از عملکردهای آن تزریق کنید.

travelService = inject(TravelService);
travelsData$: Observable<Travel[]>;
stopsList$!: Observable<Stop[]>;
constructor() {
	this.travelsData$ = this.travelService.getCollectionData(`travels`) as  Observable<Travel[]>
}

TravelService در سازنده فراخوانی می شود تا یک آرایه قابل مشاهده از همه سفرها به دست آید.

در مواردی که فقط سفرهای کاربر فعلی مورد نیاز است، از تابع query استفاده کنید.

روش‌های دیگر برای تضمین امنیت شامل اجرای قوانین امنیتی یا استفاده از توابع ابری با Firestore است که در مراحل اختیاری زیر بررسی شده است.

سپس، به سادگی توابع پیاده سازی شده در TravelService را فراخوانی کنید.

async  createTravel(userId: String) {
	this.travelService.addEmptyTravel(userId);
}

deleteTravel(travelId: String) {
	this.travelService.deleteData(`travels/${travelId}`)
}

اکنون صفحه سفرهای من باید کاربردی باشد! بررسی کنید وقتی یک پست سفر جدید ایجاد می کنید در شبیه ساز Firestore خود چه اتفاقی می افتد.

سپس، برای توابع به‌روزرسانی در /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. پیکربندی ذخیره سازی

اکنون Storage را برای ذخیره تصاویر و انواع دیگر رسانه ها پیاده سازی خواهید کرد.

Cloud Firestore به بهترین وجه برای ذخیره داده های ساختاریافته مانند اشیاء JSON استفاده می شود. Cloud Storage برای ذخیره فایل ها یا حباب ها طراحی شده است. در این برنامه از آن برای به اشتراک گذاشتن تصاویر سفر خود به کاربران استفاده خواهید کرد.

به همین ترتیب با Firestore، ذخیره و به روز رسانی فایل ها با Storage به یک شناسه منحصر به فرد برای هر فایل نیاز دارد.

بیایید توابع را در TraveService پیاده سازی کنیم:

در حال آپلود یک فایل

به src/app/services/travel.service.ts بروید و Storage را از AngularFire تزریق کنید:

export  class  TravelService {
firestore: Firestore = inject(Firestore);
auth: Auth = inject(Auth);
storage: Storage = inject(Storage);

و تابع آپلود را پیاده سازی کنید:

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;
}

تفاوت اصلی بین دسترسی به اسناد از Firestore و فایل‌ها از Cloud Storage در این است که، اگرچه هر دو مسیرهای ساخت‌یافته پوشه را دنبال می‌کنند، URL پایه و ترکیب مسیر از طریق getDownloadURL به دست می‌آیند، که سپس می‌تواند ذخیره شود و در یک فایل استفاده شود. فایل

استفاده از تابع در برنامه

به src/app/components/edit-stop/edit-stop.component.ts بروید و تابع آپلود را با استفاده از:

	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);
}

هنگامی که تصویر آپلود می شود، خود فایل رسانه در ذخیره سازی آپلود می شود و آدرس اینترنتی مطابق با آن در سند در Firestore ذخیره می شود.

9. استقرار برنامه

اکنون ما آماده استقرار برنامه هستیم!

تنظیمات firebase را از src/environments/environment.ts در src/environments/environment.prod.ts کپی کنید و اجرا کنید:

firebase deploy

شما باید چیزی شبیه به این را ببینید:

✔ 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. تبریک می گویم!

اکنون برنامه شما باید کامل شده و در میزبانی Firebase مستقر شود! همه داده‌ها و تجزیه و تحلیل‌ها اکنون در کنسول Firebase شما قابل دسترسی خواهند بود.

برای ویژگی های بیشتر در مورد AngularFire، توابع، قوانین امنیتی، فراموش نکنید که مراحل اختیاری زیر را بررسی کنید، و همچنین سایر نرم افزارهای Firebase Codelabs !

11. اختیاری: محافظان تأیید اعتبار AngularFire

همراه با Firebase Authentication، AngularFire همچنین محافظ های مبتنی بر احراز هویت را در مسیرها ارائه می دهد، به طوری که کاربران با دسترسی ناکافی می توانند هدایت شوند. این به محافظت از برنامه در برابر دسترسی کاربران به داده های محافظت شده کمک می کند.

در src/app/app-routing.module.ts ، وارد کنید

import {AuthGuard, redirectLoggedInTo, redirectUnauthorizedTo} from  '@angular/fire/auth-guard'

سپس می‌توانید عملکردهایی را تعریف کنید که کاربران در چه زمانی و به کجا باید در صفحات خاصی هدایت شوند:

const  redirectUnauthorizedToLogin = () =>  redirectUnauthorizedTo(['signin']);
const  redirectLoggedInToTravels = () =>  redirectLoggedInTo(['my-travels']);

سپس به سادگی آنها را به مسیرهای خود اضافه کنید:

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. اختیاری: قوانین امنیتی

هم Firestore و هم Cloud Storage از قوانین امنیتی (به ترتیب firestore.rules و security.rules ) برای اعمال امنیت و اعتبارسنجی داده ها استفاده می کنند.

در حال حاضر، داده های Firestore و Storage دسترسی باز برای خواندن و نوشتن دارند، اما شما نمی خواهید مردم به دنبال تغییر پست های دیگران باشند! می توانید از قوانین امنیتی برای محدود کردن دسترسی به مجموعه ها و اسناد خود استفاده کنید.

قوانین فایر استور

برای اینکه فقط به کاربران تایید شده اجازه دهید پست های سفر را مشاهده کنند، به فایل firestore.rules بروید و اضافه کنید:

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;
	}
}

قوانین امنیتی همچنین می تواند برای اعتبارسنجی داده ها استفاده شود:

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;
	}
}

قوانین ذخیره سازی

به طور مشابه، ما می توانیم از قوانین امنیتی برای اعمال دسترسی به پایگاه داده های ذخیره سازی در storage.rules استفاده کنیم. توجه داشته باشید که ما همچنین می توانیم از توابع برای بررسی های پیچیده تر استفاده کنیم:

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;
		}
	}
}