Desenvolver um site educacional de vídeos que utilize o paradigma de SPA (Single Page Application). O site deve possuir uma página de login, uma página de vídeos e uma página de gerenciamento, que permita adicionar ou remover um novo vídeo ao site.
O projeto é dividido em duas pastas: Front-End e Back-End.
Tem como função servir de plataforma pública que seja capaz de:
- Renderizar o HTML e a estilização do mesmo, criando uma interface com a qual o usuário pode interagir e enviar informações que descrevam quais partes da aplicação este quer acessar ou modificar.
- Enviar requisições HTTP que especifiquem qual método (POST, GET, DELETE) será solicitado e encapsular de maneira estruturada a informação relacionada a esta operação ao BackEnd.
- Escutar as respostas geradas pelo Backend quando este responde a uma requisição HTTP.
- Aplicar uma lógica interna que, a partir das respostas do backend, decida de qual maneira a interface do site será manipulada.
- Re-Renderizar a aplicação de maneira a refletir para o usuário a mudança do estado da aplicação feita durante as aplicações de lógica interna, bem como continuar apta a novas interações como usuário.
Tem como função servir de plataforma lógica comunicação entre o Front-End o banco de dados, que seja capaz de:
- Receber requisições HTTP enviadas pelo Front-End
- Aplicar uma lógica interna que desestruture a informação recebida pelo protocolo HTTP
- Verificar permissão. Normalmente, um token é gerado na criação de usuário e passa a ser enviado no cabeçalho das requisições. Algumas operações podem ser feitas por visitantes, já outras exigem um token de usuário, e outras token de administrador (roles)
- Enviar ao banco a requisição, agora tratada pela lógica interna
- Escutar a resposta do banco sobre a requisição feita.
- Aplicar uma lógica interna que trate o conteúdo recebido pela requisição ao banco de maneira a gerar a resposta esperada pelo FrontEnd
- Responder a requisição http ao frontend
Será utilizado o Cloud Firestorm do Google Firebase. Não será necessário o conhecimento de programação de bancos de dados, visto que este processo é automatizado pela ferramenta. Em suma, o banco recebe e responde requisições ao Back-End.
Assim como o Back-End, o banco de dados possui uma lógica interna para autenticação, caso contrário, seria possível transpassar o backend e enviar solicitações diretamente ao banco. Normalmente, é verificado se o IP que solicitou a requisição é o mesmo do IP do Back-End. Tal método de verificação já é implementado pelo FireBase.
Tanto as tecnologias utilizadas front-end quanto as no back-end ancoram-se no node.js e seu gerenciador de pacotes, o npm. Em suma, Node trata-se de um interpretador de código JavaScript de modo assíncrono e orientado a eventos, com objetivo de permitir a execução de código Javascript independentemente do Browser, ou seja, nativamente por um Servidor.
Para rodar um código javascript pelo Node, basta:
node index.jsSegue um tutorial de instalação no ubuntu e um no Windows. A versão LTS do Node já instala automaticamente o npm, gerenciador que permite instalação e distribuição facilitadas de pacotes voltados ao ambiente node.
.1 Programação funcional vs POO
.2 Event Loop
.3 JS Assíncrono: Callbacks, Promises e Async/Await
.5 Desestruturação (Essencial para entender States)
Ferramenta de versionamento que permite manter repositórios com snapshots de diversos momentos de um projeto. Github é uma plataforma que permite compartilhamento online de repositórios git. recomendamos fortemente o uso de git, pois o mesmo facilita o desenvolvimento remoto de um mesmo projeto por vários autores diferentes, bem como manter um backup da versão atual e anteriores do projeto.
Em suma, possui quatro locais/momentos de desenvolvimento:
1 - WorkSpace:
Local onde os arquivos estão sendo modificados. Para fazer de um diretório um WorkSpace de git, basta utilizar
git initPode ser mais fácil, entretanto, criar primeiramente um repositório no github, e então utilizar:
git clone url_do_repositorio Pois isto fará o estágio de push mais prático.
2 - Stage
Local onde se pode acumular diversas alterações de um arquivo, sem de fato salvá-las no repositório local. Serve como uma "caixa intermediária" entre o workspace e o repositório local.
Para adicionar um arquivo ao stage, basta utilizar
git add nome_do_arquivoE, para adicionar uma pasta inteira,
git add . 3 - Repositório Local
Local que mantém a versão mais atualizada do projeto, bem como o histórico de snapshots do mesmo com todas as versões que foram commitadas. Para adicionar o Stage ao Repositório local, basta:
git commit -m "Mensagem de commit"4 - Repositório na Nuvem - GitHub
Para subir o repositório local para a nuvem:
1- Caso tenha sido utilizado o git clone na etapa 1. , basta utilizar:
git push2 - Caso tenha sido utilizado o git init, é necessário utilizar na primeira vez:
git push --set-upstream url_do_repositorioApós isto, git push por sí só poderá ser utilizado para commits futuros.
Para boas práticas e informações mais avançadas sobre git, como Fetch/Rebase e Branches, consultar o tutorial de Git fortemente recomendado por UCLSanca
Deve ser utilizando o React para a criação da SPA, com a abordagem de Componentes Funcionais (Hooks).
A instalação e a criação de um app React é feita com:
npx create-react-app my_appPara iniciar a aplicação:
cd my_app
npm startSugere-se o uso do TailWind como FrameWork de CSS para a estilização da página. O tutorial da instalação completa em um projeto, bem como exemplos de utilização podem ser encontrado na documentação. Para desenvolvimento, por praticidade, sugere-se a instalação via CDN.
Basta incluir:
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet">Na tag <head> </head> do index.html criado automaticamente na pasta publicdo app pelo React.
Axios é um cliente que tem por objetivo enviar requests HTTP e escutar suas respostas. Segue uma boa vídeo aula que exemplifica o uso de axios em React.
Sua instalação também depende do npm, e deve ser feita Dentro de my_app
npm install axiosPor fim, deve ser importado no arquivo .js com
import axios from "axios";Sugere-se começar o desenvolvimento da aplicação pelo design das páginas, bem como sua implementação por HTML/Tailwind/CSS. Caso desejado, é possível desenhar todo o design da aplicação com alguma ferramenta de prototipação, como o Marvel App ou Adobe XD. Exemplo de páginas mockadas: Protótipo Site Digimon e Protótipo Ganesh. A aplicação não precisa ser responsiva (Mas ficaremos muito felizes se for :)), ficando a cargo do desenvolvedor escolher desenvolvê-la com foco em navegação desktop ou mobile.
Em seguida, sugere-se desenvolver a lógica da página de gerenciamento de vídeos, especificamente as funções de adicionar e remover vídeos, bem como retornar a lista. Futuramente, a lista de vídeos será requerida no Back-End. Por hora, sugere-se contornar este problema com a criação de um arquivo lista.js na pasta pública do projeto. Tal arquivo será importado por index.js e deverá possuir, além de uma lista inicialmente, vazias, funcoes getLista, AdicionaItem e DeleteItem. Componentes que se utilizem da lista também deverão importá-lo.
Não é necessário carregar vídeos inteiros na aplicação. A intenção é que se use o <embed></embed> de vídeos do youtube. A aplicação apenas salvará links para estes vídeos, mesmo quando o Back-End for implementado. A parte lógica da página de Login é amarrada ao Back-End e não é prioridade nesta etapa de desenvolvimento.
A página gerada não é persistiva, isto é, modificações na lista de vídeos se perdem ao se atualizar a página. Entretanto, deverá ser possível adicionar um vídeo pela página de gerenciamento, e acessar a lista de vídeos criados na página de vídeos. Cada página, isto é, login, cadastro, vídeos e gerenciamento deve possuir seu próprio componente.
Não é necessário se preocupar com o Axios ou com o envio de requisições e recebimento de suas respostas, que serão trabalhadas na entrega 2.
Estrutura sugerida para as pastas do projeto:
Login: public@gmail.com Senha: public
Este documento tem como objetivo especificar o backend do projeto dev.academy do USPCodeLab. Será utilizada a arquitetura REST junto com o protocolo HTTP.
Material de apoio:Tutorial básico de Node/Express
- Criar conta em firebase.google.com
- Ir em console, console.firebase.google.com/
- Criar um projeto com um nome sem caracteres especiais
- Não ativar o google analytics
Ir para o terminal
- No mesmo nível da pasta Frontend, criar uma pasta Backend
mkdir Backend
cd Backend
npx firebase-tools
npx firebase-tools login
nEm seguida, logar na conta do google (Abrirá um pop-up no navegador) e concordar com permissões. A mensagem deverá ser retornada no terminal:
Waiting for authentication...
✔ Success! Logged in as seuemail@gmail.com
Voltar para o terminal.
npx firebase-tools init
O terminal retornará:
######## #### ######## ######## ######## ### ###### ########
## ## ## ## ## ## ## ## ## ## ##
###### ## ######## ###### ######## ######### ###### ######
## ## ## ## ## ## ## ## ## ## ##
## #### ## ## ######## ######## ## ## ###### ########
You're about to initialize a Firebase project in this directory:
/home/USUARIOS/9793502/Backend
? Which Firebase CLI features do you want to set up for this folder? Press Space
to select features, then Enter to confirm your choices. (Press <space> to selec
t, <a> to toggle all, <i> to invert selection)
◯ Database: Deploy Firebase Realtime Database Rules
◯ Firestore: Deploy rules and create indexes for Firestore
❯◯ Functions: Configure and deploy Cloud Functions
◯ Hosting: Configure and deploy Firebase Hosting sites
◯ Storage: Deploy Cloud Storage security rulesSelecionar com a barra de espaço apenas functions. Apertar enter.
? Please select an option: (Use arrow keys)
❯ Use an existing project
Create a new project
Add Firebase to an existing Google Cloud Platform project
Don't set up a default project
Com o enter, selecionar use an existing project
? Please select an option: Use an existing project
? Select a default Firebase project for this directory: (Use arrow keys)
❯ myproject-2e373 (myProject)
Com o enter, escolher seu projeto.
? What language would you like to use to write Cloud Functions? (Use arrow keys)
❯ JavaScript
TypeScript
Escolher javascript. Escolher y para o linter.
? What language would you like to use to write Cloud Functions? JavaScript
? Do you want to use ESLint to catch probable bugs and enforce style? Yes
✔ Wrote functions/package.json
✔ Wrote functions/.eslintrc.json
✔ Wrote functions/index.js
✔ Wrote functions/.gitignore
? Do you want to install dependencies with npm now? (Y/n)
Escolha Y.
Foram criados vários arquivos:
- firebaserc - Arquivo de especificações.Não será manipulado.
- gitignore - Arquivo que define quais arquivos e pastas serão ignorados pelo git. Não será manipulado.
- ./functions - Pasta principal do Projeto:
- .gitignore
- package.json - Configurações do projeto firebase. Contém dependencias, scripts e o nome do projeto. Não será Manipulado
- eslintrc.json - Configurações do Linter. Não será manipulado
- index.js - Arquivo principal
index.js contém inicialmente:
const functions = require('firebase-functions');
// // Create and Deploy Your First Cloud Functions
// // https://firebase.google.com/docs/functions/write-firebase-functions
//
// exports.helloWorld = functions.https.onRequest((request, response) => {
// response.send("Hello from Firebase!");
// });Descomente o código:
const functions = require('firebase-functions');
// // Create and Deploy Your First Cloud Functions
// // https://firebase.google.com/docs/functions/write-firebase-functions
exports.helloWorld = functions.https.onRequest((request, response) => {
response.send("Hello from Firebase!");
});Em seguida, na pasta Backend, utilize o comando:
npx firebase-tools deploy --only functionsIsto irá demorar.
O console retornará o link do projeto na última linha:
✔ functions[helloWorld(us-central1)]: Successful create operation.
Function URL (helloWorld): https://us-central1-myproject-2e373.cloudfunctions.net/helloWorld
✔ Deploy complete!
Project Console: https://console.firebase.google.com/project/myproject-2e373/overviewAbra o primeiro link no navegador. Hello from Firebase! será retornado!
No projeto, utilizaremos o Express, biblioteca de node responsável por responder requisições HTTP.
Primeiramente, instale o express na pasta functions:
cd functions
npm install expressEm index.js:
- Importar o express no começo do arquivo:
const express = require('express');- Inicializar o expres em uma variável app:
const app = express();- Substituir o callback de functions.https.onRequest por app:
exports.helloWorld = functions.https.onRequest(app);- Criar a função desejada:
app.get("/oi", (req,res) => {
res.send("Bom dia do angra");
})Index final:
const functions = require('firebase-functions');
const express = require('express');
const app = express();
app.get("/oi", (req,res) => {
res.send("Bom dia do angra");
})
exports.helloWorld = functions.https.onRequest(app);O backend pode ser testado localmente, o que usualmente é mais rápido, ou deployado, o que permite seu uso por qualquer um com acesso à url.
npx firebase-tools serveNeste caso, será retornado:
=== Serving from '/home/USUARIOS/9793502/Backend'...
⚠ Your requested "node" version "8" doesn't match your global version "10"
✔ functions: Emulator started at http://localhost:5000
i functions: Watching "/home/USUARIOS/9793502/Backend/functions" for Cloud Functions...
✔ functions[helloWorld]: http function initialized (http://localhost:5000/myproject-2e373/us-central1/helloWorld).
i functions: Beginning execution of "helloWorld"
i functions: Finished "helloWorld" in ~1s
Neste caso, o root de teste será http://localhost:5000/myproject-2e373/us-central1/helloWorld.
A resposta à requisições get dadas no endpoint /oi podem ser acessadas, portanto, em http://localhost:5000/myproject-2e373/us-central1/helloWorld/oi
npx firebase-tools deployObservações:
- exports da função deve ser última coisa do código.
- O link das funções de seu projeto estão disponíveis em https://console.firebase.google.com/project/NOME_DO_SEU_PROJETO/functions/list
- Usualmente, cria-se apenas uma função e controla-se os recursos da aplicação pelos endpoints de argumento em
app.algo('/endpoint') - O "caminho root" é o que aparece na lista em 2.. No caso, https://us-central1-myproject-2e373.cloudfunctions.net/helloWorld.
- Para utilizar o recurso em "/oi", portanto, deve-se acessar a URL https://us-central1-myproject-2e373.cloudfunctions.net/helloWorld/oi
REST (Representational state transfer) é uma arquitetura para organizar APIs (como um backend). Ela descreve o significado semântico de cada parâmetro de uma requisição HTTP. Um HTTP Request tem os seguintes parâmetros:
-
Método: descrevem a ação do seu Request. Os mais populares métodos são:
- GET: Ação de ler dados.
- POST: Ação de escrever dados.
- DELETE: Ação de deletar dados.
- PATCH: Ação de modificar dados já existentes.
-
URI, Path ou Endpoint: é um identificador de recurso. Descreve qual o recurso que o Request está acessando. Exemplo de um Path: “/users/admin.json”
-
Headers: Informações adicionais sobre o Request. Normalmente descrevem coisas como permissões, tipo do conteúdo, etc…
-
Body: Corpo da requisição. O corpo contém as principais informações da requisição. Em REST, o conteúdo deve ser no formato JSON.
Cada requisição deve ter uma resposta (tambem no formato HTTP). Uma resposta tem os seguintes parâmetros:
-
Status Code: O Status Code de uma resposta indica se o Request foi bem sucedido ou não. Alguns status code famosos são:
- 200: OK! Deu tudo certo!
- 404: Não encontrado. O recurso ao qual o Request se refere não pode ser encontrado.
- 500: Erro interno do servidor. O servidor fez alguma besteira.
-
Headers: Análogos aos headers de requisições, porêm são dados adicionais à resposta.
-
body: Tambem análogo ao corpo de requisições. É onde os dados respondidos devem ser enviados, no formato JSON.
Em REST, cada requisição deve ser referente a um recurso do servidor (especificado pelo endpoint). O método da requisição deve descrever a ação a ser tomada neste recurso (GET - ler, POST - criar novo, DELETE - deletar, PATCH - editar). O corpo contem os dados necessarios para a ação desejada (exemplo: informações de um usuario para um login).
A resposta da requisição requer apenas que o Status Code seja semântico.
Index:
Index:
Contém os seguintes dados referentes aos usuários:
- Senha Criptografada
Método: POST
Endpoint: /users
Não requer autenticação
Corpo da requisição:
{
email: string,
password: string
}
Corpo da resposta quando sucesso (200): Vazio
Corpo da resposta quando email invalido (400):
{
message: "Email is not valid"
}
Corpo da resposta quando senha invalida (400):
{
message: "Password is not valid"
}
Corpo da resposta quando email já existe (400):
{
message: "Email is already in use"
}
Método: POST
Endpoint: /users/login
Não requer autenticação
Corpo da requisição:
{
email: string,
password: string
}
Corpo da resposta quando sucesso (200):
{
token: string
}
Corpo da resposta quando credenciais incorretas (400):
{
message: "invalid email/password"
}
Método: GET
Endpoint: /users
Não requer autenticação
Corpo da requisição: Vazio
Corpo da resposta:
{
users: {email: string}[]
}
Método: DELETE
Endpoint: /users/:id
requer autenticação (necessita um token)
Corpo da requisição: Vazio
Corpo da resposta quando sucesso(200): Vazio
Corpo da resposta quando não se está logado (400)
{
message: "You must be logged in"
}
Corpo da resposta caso o usuario não exista (400)
{
message: "User not found"
}
O usuario só pode ser deletado por si mesmo
Contem os seguintes dados de vídeos:
- timestamp
- email do usuário criador
- url do video
- nome do video
- descrição do video
- ID do video
Método: POST
Endpoint: /videos
Requer autenticação
Corpo da requisição:
{
timestamp: number,
ownerEmail: string,
url: string,
title: string,
description: string
}
Corpo da resposta quando sucessor (200):
{
videoId: string
}
Corpo da resposta quando não se esta logado (400):
{
message: "You must be logged in"
}
Corpo da resposta quando alguma informação do video esta incorreta (400):
{
message: "invalid video info"
}
Método: GET
Endpoint: /videos
Não requer autenticação
Corpo da requisição: Vazio
Corpo da resposta:
{
videos: {
timestamp: number,
ownerEmail: string,
url: string,
title: string,
description: string,
id: string
}[]
}
Método: DELETE
Endpoint: /videos/:id
requer autenticação
Corpo da requisição: Vazio
Corpo da resposta quando sucesso (200): Vazio
Corpo da resposta quando não se está logado:
{
message: "You must be logged in"
}
Corpo da resposta quando o video não é do usuario logado (400):
{
message: "Not enough permissions"
}
Corpo da resposta quando o video não existe (400):
{
message: "video not found"
}
O vídeo só pode ser deletado pelo seu criador


