portaldacalheta.pt
  • Principal
  • Planejamento E Previsão
  • Design De Iu
  • Design Móvel
  • Pessoas E Equipes De Produto
Web Front-End

Como criar uma API baseada em papéis com Firebase Authentication



Neste tutorial, construiremos uma API REST para gerenciar usuários e funções usando Firebase e Node.js. Além disso, veremos como usar a API para autorizar (ou não) quais usuários podem acessar recursos específicos.

Introdução

Quase todo aplicativo requer algum nível de sistema de autorização. Em alguns casos, validar um nome de usuário / senha definido com nossa tabela de Usuários é suficiente, mas frequentemente, precisamos de um modelo de permissões mais refinado para permitir que certos usuários acessem certos recursos e os restrinja de outros. Construir um sistema para suportar o último não é trivial e pode consumir muito tempo. Neste tutorial, aprenderemos como construir uma API de autenticação baseada em papéis usando o Firebase, o que nos ajudará a começar a funcionar rapidamente.



Autenticação baseada em funções

Neste modelo de autorização, o acesso é concedido a funções, em vez de usuários específicos, e um usuário pode ter uma ou mais dependendo de como você projeta seu modelo de permissão. Os recursos, por outro lado, requerem certas funções para permitir que um usuário os execute.



Autenticação baseada em funções com ilustrado



Firebase

Firebase Authentication

Em suma, o Firebase Authentication é um sistema de autenticação baseado em token extensível e fornece integrações prontas para uso com os provedores mais comuns, como Google, Facebook e Twitter, entre outros.

Ele nos permite usar declarações personalizadas que usaremos para construir uma API flexível baseada em funções.



Podemos definir qualquer valor JSON nas declarações (por exemplo, { role: 'admin' } ou { role: 'manager' }).

Depois de definidas, as declarações personalizadas serão incluídas no token que o Firebase gera, e podemos ler o valor para controlar o acesso.



Ele também vem com uma cota gratuita muito generosa, que na maioria dos casos será mais do que suficiente.

Funções do Firebase

As funções são um serviço de plataforma sem servidor totalmente gerenciado. Precisamos apenas escrever nosso código em Node.js e implantá-lo. O Firebase cuida do dimensionamento da infraestrutura sob demanda, configuração do servidor e muito mais. Em nosso caso, vamos usá-lo para construir nossa API e expô-lo via HTTP para a web.



O Firebase nos permite definir express.js aplicativos como manipuladores para caminhos diferentes - por exemplo, você pode criar um aplicativo Express e conectá-lo a /mypath, e todas as solicitações que chegam a esta rota serão manipuladas pelo app configurado.

No contexto de uma função, você tem acesso a toda a API Firebase Authentication, usando o SDK Admin.



É assim que vamos criar a API do usuário.

O que vamos construir

Então, antes de começar, vamos dar uma olhada no que iremos construir. Vamos criar uma API REST com os seguintes endpoints:



Http Verb Caminho Descrição Autorização
OBTER /Comercial Lista todos os usuários Apenas administradores e gerentes têm acesso
POSTAR /Comercial Cria novo usuário Apenas administradores e gerentes têm acesso
OBTER / users /: id Obtém o usuário: id Administradores, gerentes e o mesmo usuário que: id têm acesso
FRAGMENTO / users /: id Atualiza o usuário: id Administradores, gerentes e o mesmo usuário que: id têm acesso
EXCLUIR / users /: id Exclui o usuário: id Administradores, gerentes e o mesmo usuário que: id têm acesso

Cada um desses endpoints tratará da autenticação, validará a autorização, executará a operação correspondente e, finalmente, retornará um código HTTP significativo.

Criaremos as funções de autenticação e autorização necessárias para validar o token e verificar se as declarações contêm a função necessária para executar a operação.

Construindo a API

Para construir a API, precisamos:

  • Um projeto Firebase
  • firebase-tools instalado

Primeiro, faça login no Firebase:

firebase login

Em seguida, inicialize um projeto do Functions:

firebase init ? Which Firebase CLI features do you want to set up for this folder? ... (O) Functions: Configure and deploy Cloud Functions ? Select a default Firebase project for this directory: {your-project} ? What language would you like to use to write Cloud Functions? TypeScript ? Do you want to use TSLint to catch probable bugs and enforce style? Yes ? Do you want to install dependencies with npm now? Yes

Neste ponto, você terá uma pasta de funções, com configuração mínima para criar funções do Firebase.

Em src/index.ts há um helloWorld exemplo, que você pode descomentar para validar que suas funções funcionam. Então você pode cd functions e execute npm run serve. Este comando irá transpilar o código e iniciar o servidor local.

Você pode verificar os resultados em http: // localhost: 5000 / {seu-projeto} / us-central1 / helloWorld

como é um vazamento de memória

Um novo aplicativo Firebase

Observe que a função é exposta no caminho definido como o nome dela em 'index.ts: 'helloWorld'.

Criação de uma função HTTP do Firebase

Agora vamos codificar nossa API. Vamos criar uma função http Firebase e conectá-la a /api caminho.

Primeiro, instale npm install express.

No src/index.ts vamos:

  • Inicialize o módulo Firebase-admin SDK com admin.initializeApp();
  • Defina um aplicativo Express como o manipulador de nosso api endpoint https
import * as functions from 'firebase-functions'; import * as admin from 'firebase-admin'; import * as express from 'express'; admin.initializeApp(); const app = express(); export const api = functions.https.onRequest(app);

Agora, todas as solicitações indo para /api será tratado pelo app instância.

A próxima coisa que faremos é configurar o app instância para suportar CORS e adicionar middleware de analisador de corpo JSON. Dessa forma, podemos fazer solicitações de qualquer URL e analisar solicitações formatadas em JSON.

Instalaremos primeiro as dependências necessárias.

npm install --save cors body-parser npm install --save-dev @types/cors

E depois:

//... import * as cors from 'cors'; import * as bodyParser from 'body-parser'; //... const app = express(); app.use(bodyParser.json()); app.use(cors({ origin: true })); export const api = functions.https.onRequest(app);

Por fim, configuraremos as rotas que app vai lidar com.

//... import { routesConfig } from './users/routes-config'; //… app.use(cors({ origin: true })); routesConfig(app) export const api = functions.https.onRequest(app);

O Firebase Functions permite definir um aplicativo Express como o manipulador e qualquer caminho após aquele que você configurou em functions.https.onRequest(app); —neste caso, api —também será tratado pelo app . Isso nos permite escrever pontos de extremidade específicos, como api/users e definir um manipulador para cada verbo HTTP, o que faremos a seguir.

Vamos criar o arquivo src/users/routes-config.ts

Aqui, definiremos um create manipulador em POST '/users'

import { Application } from 'express'; import { create} from './controller'; export function routesConfig(app: Application) { app.post('/users', create ); }

Agora, vamos criar o src/users/controller.ts Arquivo.

Nessa função, primeiro validamos se todos os campos estão na solicitação de corpo e, em seguida, criamos o usuário e definimos as declarações personalizadas.

Estamos apenas passando { role } no setCustomUserClaims —os outros campos já estão definidos pelo Firebase.

Se nenhum erro ocorrer, retornamos um código 201 com uid do usuário criado.

import { Request, Response } from 'express'; import * as admin from 'firebase-admin' export async function create(req: Request, res: Response) { try { const { displayName, password, email, role } = req.body if (!displayName || !password || !email || !role) { return res.status(400).send({ message: 'Missing fields' }) } const { uid } = await admin.auth().createUser({ displayName, password, email }) await admin.auth().setCustomUserClaims(uid, { role }) return res.status(201).send({ uid }) } catch (err) { return handleError(res, err) } } function handleError(res: Response, err: any) { return res.status(500).send({ message: `${err.code} - ${err.message}` }); }

Agora, vamos proteger o manipulador adicionando autorização. Para fazer isso, adicionaremos alguns manipuladores ao nosso create ponto final. Com express.js, você pode definir uma cadeia de manipuladores que serão executados em ordem. Em um manipulador, você pode executar o código e passá-lo para o next() manipulador ou retornar uma resposta. O que vamos fazer é primeiro autenticar o usuário e depois validar se ele está autorizado a executar.

No arquivo src/users/routes-config.ts:

//... import { isAuthenticated } from '../auth/authenticated'; import { isAuthorized } from '../auth/authorized'; export function routesConfig(app: Application) { app.post('/users', isAuthenticated, isAuthorized({ hasRole: ['admin', 'manager'] }), create ); }

Vamos criar os arquivos src/auth/authenticated.ts.

Nesta função, validaremos a presença de authorization token do portador no cabeçalho da solicitação. Então iremos decodificá-lo com admin.auth().verifyidToken() e persistir o usuário uid, role e email no res.locals variável, que usaremos posteriormente para validar a autorização.

Caso o token seja inválido, retornamos uma resposta 401 ao cliente:

import { Request, Response } from 'express'; import * as admin from 'firebase-admin' export async function isAuthenticated(req: Request, res: Response, next: Function) { const { authorization } = req.headers if (!authorization) return res.status(401).send({ message: 'Unauthorized' }); if (!authorization.startsWith('Bearer')) return res.status(401).send({ message: 'Unauthorized' }); const split = authorization.split('Bearer ') if (split.length !== 2) return res.status(401).send({ message: 'Unauthorized' }); const token = split[1] try { const decodedToken: admin.auth.DecodedIdToken = await admin.auth().verifyIdToken(token); console.log('decodedToken', JSON.stringify(decodedToken)) res.locals = { ...res.locals, uid: decodedToken.uid, role: decodedToken.role, email: decodedToken.email } return next(); } catch (err) { console.error(`${err.code} - ${err.message}`) return res.status(401).send({ message: 'Unauthorized' }); } }

Agora, vamos criar um src/auth/authorized.ts Arquivo.

Neste manipulador, extraímos as informações do usuário de res.locals definimos previamente e validamos se ele tem a função necessária para executar a operação ou no caso de a operação permitir que o mesmo usuário execute, validamos se o ID nos parâmetros de solicitação é o mesmo do token de autenticação. Se o usuário não tiver a função exigida, retornaremos um 403.

import { Request, Response } from 'express'; export function isAuthorized(opts: { hasRole: Array, allowSameUser?: boolean }) { return (req: Request, res: Response, next: Function) => { const { role, email, uid } = res.locals const { id } = req.params if (opts.allowSameUser && id && uid === id) return next(); if (!role) return res.status(403).send(); if (opts.hasRole.includes(role)) return next(); return res.status(403).send(); } }

Com esses dois métodos, seremos capazes de autenticar solicitações e autorizá-las de acordo com o role no token de entrada. Isso é ótimo, mas como o Firebase não nos permite definir reivindicações personalizadas do projeto console , não poderemos executar nenhum desses endpoints. Para contornar isso, podemos criar um usuário root no Firebase Authentication Console

Criação de um usuário no Firebase Authentication Console

E defina uma comparação de e-mail no código. Agora, ao disparar solicitações deste usuário, poderemos executar todas as operações.

//... const { role, email, uid } = res.locals const { id } = req.params if (email === ' [email protected] ') return next(); //...

Agora, vamos adicionar o resto das operações CRUD a src/users/routes-config.ts.

Para operações de obter ou atualizar um único usuário, onde :id param for enviado, também permitimos que o mesmo usuário execute a operação.

export function routesConfig(app: Application) { //.. // lists all users app.get('/users', [ isAuthenticated, isAuthorized({ hasRole: ['admin', 'manager'] }), all ]); // get :id user app.get('/users/:id', [ isAuthenticated, isAuthorized({ hasRole: ['admin', 'manager'], allowSameUser: true }), get ]); // updates :id user app.patch('/users/:id', [ isAuthenticated, isAuthorized({ hasRole: ['admin', 'manager'], allowSameUser: true }), patch ]); // deletes :id user app.delete('/users/:id', [ isAuthenticated, isAuthorized({ hasRole: ['admin', 'manager'] }), remove ]); }

E em src/users/controller.ts. Nessas operações, aproveitamos o SDK do administrador para interagir com o Firebase Authentication e realizar as respectivas operações. Como fizemos anteriormente em create operação, retornamos um código HTTP significativo em cada operação.

Para a operação de atualização, validamos todos os campos presentes e substituímos customClaims com aqueles enviados na solicitação:

//.. export async function all(req: Request, res: Response) { try { const listUsers = await admin.auth().listUsers() const users = listUsers.users.map(mapUser) return res.status(200).send({ users }) } catch (err) { return handleError(res, err) } } function mapUser(user: admin.auth.UserRecord) { const customClaims = (user.customClaims || { role: '' }) as { role?: string } const role = customClaims.role ? customClaims.role : '' return uid: user.uid, email: user.email } export async function get(req: Request, res: Response) { try { const { id } = req.params const user = await admin.auth().getUser(id) return res.status(200).send({ user: mapUser(user) }) } catch (err) { return handleError(res, err) } } export async function patch(req: Request, res: Response) { try { const { id } = req.params const { displayName, password, email, role } = req.body if (!id || !displayName || !password || !email || !role) { return res.status(400).send({ message: 'Missing fields' }) } await admin.auth().updateUser(id, { displayName, password, email }) await admin.auth().setCustomUserClaims(id, { role }) const user = await admin.auth().getUser(id) return res.status(204).send({ user: mapUser(user) }) } catch (err) { return handleError(res, err) } } export async function remove(req: Request, res: Response) { try { const { id } = req.params await admin.auth().deleteUser(id) return res.status(204).send({}) } catch (err) { return handleError(res, err) } } //...

Agora podemos executar a função localmente. Para fazer isso, primeiro você precisa configurar a chave da conta para poder se conectar com a API de autenticação localmente. Então corra:

npm run serve

Implante a API

Ótimo! Agora que escrevemos a API baseada em funções, podemos implantá-la na web e começar a usá-la. A implantação com o Firebase é super fácil, só precisamos executar firebase deploy. Assim que a implantação for concluída, podemos acessar nossa API no URL publicado.

Executar o comando firebase deploy

Você pode verificar o URL da API em https://console.firebase.google.com/u/0/project/[your-project concepts/functions/list .

O URL da API no Firebase Console

No meu caso é https://us-central1-joaq-lab.cloudfunctions.net/api .

Consumindo a API

Depois que nossa API for implantada, temos várias maneiras de usá-la - neste tutorial, vou cobrir como usá-la via Postman ou de um aplicativo Angular.

Se inserirmos o URL Listar todos os usuários (/api/users) em qualquer navegador, obteremos o seguinte:

API Firebase Authentication

A razão para isso é que, ao enviar a solicitação de um navegador, estamos executando uma solicitação GET sem cabeçalhos de autenticação. Isso significa que nossa API está realmente funcionando conforme o esperado!

Nossa API é protegida por tokens - para gerar tal token, precisamos chamar o SDK do cliente do Firebase e fazer login com uma credencial de usuário / senha válida. Quando for bem-sucedido, o Firebase enviará um token de volta na resposta que podemos adicionar ao cabeçalho de qualquer solicitação a seguir que quisermos realizar.

De um aplicativo angular

Neste tutorial, examinarei apenas as partes importantes para consumir a API de um aplicativo Angular. O repositório completo pode ser acessado Aqui , e se você precisar de um tutorial passo a passo sobre como criar um aplicativo Angular e configurar @ angular / fire para usar, você pode verificar isto postar .

Então, voltando ao login, teremos um SignInComponent com um permite que o usuário insira um nome de usuário e uma senha.

//... Email address Password //...

E na aula, nós signInWithEmailAndPassword usando AngularFireAuth serviço.

//... form: FormGroup = new FormGroup({ email: new FormControl(''), password: new FormControl('') }) constructor( private afAuth: AngularFireAuth ) { } async signIn() { try { const { email, password } = this.form.value await this.afAuth.auth.signInWithEmailAndPassword(email, password) } catch (err) { console.log(err) } } //..

Neste ponto, podemos fazer login em nosso projeto Firebase.

Login pelo aplicativo Angular

A resposta da API ao fazer login no aplicativo Angular

E quando inspecionamos as solicitações de rede no DevTools, podemos ver que o Firebase retorna um token após verificar nosso usuário e senha.

Esse token é o que usaremos para enviar a solicitação de nosso cabeçalho à API que criamos. Uma maneira de adicionar o token a todas as solicitações é usando um HttpInterceptor.

Este arquivo mostra como obter o token de AngularFireAuth e adicione-o à solicitação do cabeçalho. Em seguida, fornecemos o arquivo interceptor no AppModule.

http-interceptors / auth-token.interceptor.ts

@Injectable({ providedIn: 'root' }) export class AuthTokenHttpInterceptor implements HttpInterceptor { constructor( private auth: AngularFireAuth ) { } intercept(req: HttpRequest, next: HttpHandler): Observable { return this.auth.idToken.pipe( take(1), switchMap(idToken => { let clone = req.clone() if (idToken) { clone = clone.clone({ headers: req.headers.set('Authorization', 'Bearer ' + idToken) }); } return next.handle(clone) }) ) } } export const AuthTokenHttpInterceptorProvider = { provide: HTTP_INTERCEPTORS, useClass: AuthTokenHttpInterceptor, multi: true }

app.module.ts

@NgModule({ //.. providers: [ AuthTokenHttpInterceptorProvider ] //... }) export class AppModule { }

Assim que o interceptor estiver definido, podemos fazer solicitações à nossa API de httpClient. Por exemplo, aqui está um UsersService onde chamamos a lista de todos os usuários, obtemos o usuário por seu ID, criamos um usuário e atualizamos um usuário.

//… export type CreateUserRequest = { displayName: string, password: string, email: string, role: string } export type UpdateUserRequest = { uid: string } & CreateUserRequest @Injectable({ providedIn: 'root' }) export class UserService { private baseUrl = '{your-functions-url}/api/users' constructor( private http: HttpClient ) { } get users$(): Observable { return this.http.get(`${this.baseUrl}`).pipe( map(result => { return result.users }) ) } user$(id: string): Observable { return this.http.get(`${this.baseUrl}/${id}`).pipe( map(result => { return result.user }) ) } create(user: CreateUserRequest) { return this.http.post(`${this.baseUrl}`, user) } edit(user: UpdateUserRequest) { return this.http.patch(`${this.baseUrl}/${user.uid}`, user) } }

Agora, podemos chamar a API para obter o usuário conectado por seu ID e listar todos os usuários de um componente como este:

//...

Me

  • {{user.displayName}}
    {{user.email}} {{user.role?.toUpperCase()}}

All Users

  • {{user.displayName}}
    {{user.email}} {{user.uid}} {{user.role?.toUpperCase()}}
//...
//... users$: Observable user$: Observable constructor( private userService: UserService, private userForm: UserFormService, private modal: NgbModal, private afAuth: AngularFireAuth ) { } ngOnInit() { this.users$ = this.userService.users$ this.user$ = this.afAuth.user.pipe( filter(user => !!user), switchMap(user => this.userService.user$(user.uid)) ) } //...

E aqui está o resultado.

Todos os usuários em nosso aplicativo Angular

Observe que se entrarmos com um usuário com role=user, apenas a seção Eu será renderizada.

A visualização do recurso do usuário ao qual o usuário com a função de usuário tem acesso

E obteremos um 403 no inspetor de rede. Isso se deve à restrição que definimos anteriormente na API para permitir apenas que “Administradores” listem todos os usuários.

Um erro 403 no inspetor de rede

Agora, vamos adicionar as funcionalidades “criar usuário” e “editar usuário”. Para fazer isso, vamos criar primeiro um UserFormComponent e um UserFormService.

{ async}

× Email address Password Display Name Role Admin Manager User Cancel Save
@Component({ selector: 'app-user-form', templateUrl: './user-form.component.html', styleUrls: ['./user-form.component.scss'] }) export class UserFormComponent implements OnInit { form = new FormGroup({ uid: new FormControl(''), email: new FormControl(''), displayName: new FormControl(''), password: new FormControl(''), role: new FormControl(''), }); title$: Observable; user$: Observable; constructor( public modal: NgbActiveModal, private userService: UserService, private userForm: UserFormService ) { } ngOnInit() { this.title$ = this.userForm.title$; this.user$ = this.userForm.user$.pipe( tap(user => { if (user) { this.form.patchValue(user); } else { this.form.reset({}); } }) ); } dismiss() { this.modal.dismiss('modal dismissed'); } save() { const { displayName, email, role, password, uid } = this.form.value; this.modal.close({ displayName, email, role, password, uid }); } } import { Injectable } from '@angular/core'; import { BehaviorSubject } from 'rxjs'; import { map } from 'rxjs/operators'; @Injectable({ providedIn: 'root' }) export class UserFormService { _BS = new BehaviorSubject({ title: '', user: {} }); constructor() { } edit(user) { this._BS.next({ title: 'Edit User', user }); } create() { this._BS.next({ title: 'Create User', user: null }); } get title$() { return this._BS.asObservable().pipe( map(uf => uf.title) ); } get user$() { return this._BS.asObservable().pipe( map(uf => uf.user) ); } }

De volta ao componente principal, vamos adicionar os botões para chamar essas ações. Nesse caso, “Editar usuário” estará disponível apenas para o usuário conectado. Você pode ir em frente e adicionar a funcionalidade para editar outros usuários, se necessário!

//...

Me

Edit Profile //...

All Users

New User //...
//... create() { this.userForm.create(); const modalRef = this.modal.open(UserFormComponent); modalRef.result.then(user => { this.userService.create(user).subscribe(_ => { console.log('user created'); }); }).catch(err => { }); } edit(userToEdit) { this.userForm.edit(userToEdit); const modalRef = this.modal.open(UserFormComponent); modalRef.result.then(user => { this.userService.edit(user).subscribe(_ => { console.log('user edited'); }); }).catch(err => { }); }

Do carteiro

Postman é uma ferramenta para construir e fazer solicitações a APIs. Desta forma, podemos simular que estamos chamando nossa API de qualquer aplicativo cliente ou serviço diferente.

O que vamos demonstrar é como enviar uma solicitação para listar todos os usuários.

Depois de abrir a ferramenta, definimos o URL https: // us-central1- {your-project} .cloudfunctions.net / api / users :

O URL da API carregado no campo Postman pronto para disparar como uma solicitação GET

A seguir, na autorização da aba, escolhemos Bearer Token e configuramos o valor que extraímos das Ferramentas de Desenvolvimento anteriormente.

Configurando o token do portador no Postman

como fazer um token

O corpo da resposta que recebemos

Conclusão

Parabéns! Você concluiu todo o tutorial e agora aprendeu a criar uma API baseada na função do usuário no Firebase.

Também abordamos como consumi-lo em um aplicativo Angular e no Postman.

Vamos recapitular as coisas mais importantes:

  1. O Firebase permite que você comece a trabalhar rapidamente com uma API de autenticação de nível empresarial, que você pode estender mais tarde.
  2. Quase todos os projetos exigem autorização - se você precisar controlar o acesso usando um modelo baseado em funções, o Firebase Authentication permite que você comece muito rapidamente.
  3. O modelo baseado em funções depende da validação de recursos que são solicitados de usuários com funções específicas versus usuários específicos.
  4. Usando um aplicativo Express.js na função Firebase, podemos criar uma API REST e definir manipuladores para autenticar e autorizar solicitações.
  5. Aproveitando as declarações personalizadas integradas, você pode criar uma API de autenticação baseada em funções e proteger seu aplicativo.

Você pode ler mais sobre o Firebase auth Aqui . E se você quiser alavancar as funções que definimos, você pode usar @ angular / fire ajudantes .

Compreender o básico

O Firebase Auth é uma API REST?

Firebase Auth é um serviço que permite que seu aplicativo se inscreva e autentique um usuário em vários provedores, como (Google, Facebook, Twitter, GitHub e mais). O Firebase Auth fornece SDKs com os quais você pode se integrar facilmente com a Web, Android e iOS. Firebase Auth também pode ser consumido como uma API REST

Para que é usado o Firebase?

O Firebase é um pacote de produtos em nuvem que ajuda a criar um aplicativo móvel ou web sem servidor muito rapidamente. Ele fornece a maioria dos serviços comuns envolvidos em cada aplicativo (banco de dados, autorização, armazenamento, hospedagem).

Como faço para obter a API Firebase Auth?

Você pode criar um projeto com sua conta do Google em firebase.google.com. Depois de criar o projeto, você pode ativar o Firebase Auth e começar a usá-lo no seu aplicativo.

Qual é melhor, Firebase ou AWS?

O Firebase é um produto apoiado pelo Google, e um dos quais o Google está tentando expandir e adicionar mais e mais recursos. O AWS Amplify é um produto semelhante, voltado principalmente para aplicativos móveis. Ambos são ótimos produtos, com o Firebase sendo um produto mais antigo com mais recursos.

O Firebase é fácil de usar?

O Firebase é um serviço totalmente gerenciado com o qual você pode começar com muita facilidade e não se preocupar com a infraestrutura quando precisar escalonar. Há uma grande quantidade de documentação e postagens de blog com exemplos para aprender rapidamente como funciona.

O Firebase é bom para grandes bancos de dados?

O Firebase tem dois bancos de dados: Realtime Database e Firestore. Ambos são bancos de dados NoSQL com recursos semelhantes e modelos de preços diferentes. O Firestore oferece suporte a melhores recursos de consulta e ambos os bancos de dados são projetados para que a latência de consulta não seja afetada pelo tamanho do banco de dados.

Aishwarya foi enganada por segurar a mão da filha Aaradhya. Quando é a hora certa para deixar ir?

Família

Aishwarya foi enganada por segurar a mão da filha Aaradhya. Quando é a hora certa para deixar ir?
As questões que intrigam Paris: O que aconteceu com Abdelhamid Abaaoud?

As questões que intrigam Paris: O que aconteceu com Abdelhamid Abaaoud?

Noticias Do Mundo

Publicações Populares
‘Stormy Daniels lembrou Donald Trump da filha Ivanka’: cinco tópicos da entrevista da CBS '60 Minutes ’
‘Stormy Daniels lembrou Donald Trump da filha Ivanka’: cinco tópicos da entrevista da CBS '60 Minutes ’
Design de botão ao longo dos anos - A linha do tempo do Dribbble
Design de botão ao longo dos anos - A linha do tempo do Dribbble
Fazendo a mudança stick: como obter o gerenciamento de mudança certo
Fazendo a mudança stick: como obter o gerenciamento de mudança certo
Blues da indústria de kits de refeição: Como o avental azul pode aliviar seu mal-estar?
Blues da indústria de kits de refeição: Como o avental azul pode aliviar seu mal-estar?
Um guia para motores Rails na natureza: exemplos do mundo real de motores Rails em ação
Um guia para motores Rails na natureza: exemplos do mundo real de motores Rails em ação
 
Primeiras impressões - um guia para integração de experiência do usuário
Primeiras impressões - um guia para integração de experiência do usuário
Terremoto de magnitude 6,7 atinge o Chile, sem ameaça de tsunami
Terremoto de magnitude 6,7 atinge o Chile, sem ameaça de tsunami
EdTech Industry Analysis & Trends (2020)
EdTech Industry Analysis & Trends (2020)
Táticas e estratégias de negociação de fusões e aquisições: dicas de um profissional
Táticas e estratégias de negociação de fusões e aquisições: dicas de um profissional
Cinco etapas para o sucesso: uma lista de verificação de arrecadação de fundos de capital privado
Cinco etapas para o sucesso: uma lista de verificação de arrecadação de fundos de capital privado
Publicações Populares
  • como definir o preço de uma opção
  • a experiência é impossível de medir porque é um sentimento.
  • como escrever um documento de design técnico
  • como fazer um vídeo em efeitos posteriores
  • comprar cartão de crédito online de hackers
  • Calculadora de custos do empregador para compensação do empregado
  • qual site oferece um tutorial para aprender programação c
Categorias
  • Planejamento E Previsão
  • Design De Iu
  • Design Móvel
  • Pessoas E Equipes De Produto
  • © 2022 | Todos Os Direitos Reservados

    portaldacalheta.pt