[MUSIC]
Nós já tínhamos desenvolvido um servidor API REST completo usando Express e
MongoDB como parte deste curso.
Para que o servidor possa se comunicar de forma significativa com nosso cliente,
faremos alguns pequenos ajustes para que ele retorne o tipo certo de dados.
Para que a implementação de nosso cliente possa trabalhar de forma mais eficiente
com os dados retornados do lado do servidor.
Então, para fazer isso,
vamos trabalhar em alguns ajustes para o nosso lado do servidor neste exercício.
Indo ao nosso servidor no editor, antes de começarmos a trabalhar no servidor,
sugiro que você baixe todas as imagens que forneci
como um arquivo zip nos recursos de exercício chamados images.zip.
Descompacte o arquivo e, em seguida, obtenha todas as imagens de lá e, em
seguida, copie essas imagens para a pasta de imagens públicas em nosso servidor.
Então você vê que aqui eu copiei todas as imagens para a minha
pasta de imagens públicas aqui.
Porque o nosso servidor é aquele que vai servir todas essas imagens para a
nossa aplicação cliente.
Em seguida, vamos para os cors e ajustamos essa lista branca, aqui.
Então, para o nosso aplicativo cliente Angular, se iniciarmos
com o comando ng serve, ele será executado no localhost :4200.
Portanto, quaisquer pedidos que venham da nossa
aplicação Angular para o servidor levarão isso como sua origem lá.
Então é por isso que vou adicionar isso à minha lista branca, para
que quaisquer problemas de cors sejam resolvidos automaticamente.
Então, indo para o arquivo cors.js,
na minha lista branca, aqui, deixe-me adicionar
no http://localhost:, 4200.
E esta é a origem da qual todo o meu cliente Angular será
originado o pedido que vier a este servidor.
Assim, meus cors não causarão problemas para meu cliente Angular.
Em seguida, precisamos atualizar algumas das rotas para lidar com
os parâmetros de consulta, e também alguns pequenos outros ajustes.
Deixe-me começar com os arquivos promoRouter.js.
Então isso é simples de se atualizar.
Então, indo para o arquivo promoRouter.js, no arquivo PromOrouter, para
a solicitação get que recebemos aqui,
em vez de fazer promotions.Find com um JavaScript vazio,
aqui eu forneceria o req.query como
o parâmetro para que promotions.Find aqui. A
mesma coisa com o LeaderRouter também, então deixe-me ir para o arquivo leaderRouter.js.
E no LeaderRouter também,
aqui onde você encontra Leaders.Find com o objeto JavaScript vazio.
Em vez disso, substitua esse req.query, para
que os parâmetros de consulta sejam passados.
Então, este é o lugar onde vamos passar na coluna em destaque
através como o parâmetro de consulta.
Agora tendo ajustado esses dois, vamos agora trabalhar na rota do prato,
então indo para o arquivo dishRouter.js, mesmo no DishRouter, a mesma atualização aqui.
Então, indo para este dishes.Find no método get aqui, altere isso para req.query.
Então, com isso, minha atualização DISHRouter foi concluída.
Então, agora atualizamos o PromOrouter, o ReaderRouter e
o DisishRouter, então vamos passar para atualizar esse FavoriteOuter.
Agora você teria implementado o roteador favorito como parte de sua
quarta atribuição.
Agora, no FavoriterOuter, você verá que para
o FavoriterOuter eu não estou mostrando o parter restante porque
você deveria ter feito como parte de sua tarefa.
Deixe-me primeiro chamar sua atenção para o método get para
o favoriteRouter.route (“/:dishid').
Agora, eu vou usar este método get para apenas
verificar para garantir que o prato específico com
um DishID já é um favorito para o usuário.
Então, em vez de simplesmente dizer operação GET não suportada,
eu vou apenas alavancar a presença desta operação get.
E então diremos,
favoritos. Findone.
E eu vou dizer,
usuário: req.user.id
Então vamos encontrar os favoritos para esse usuário em particular.
E então diremos, então, favoritos.
E, catch ((err),
próximo (err)).
E então, da mesma forma aqui, adicionaremos o erro aqui.
Próximo (err)), aqui.
Então, dentro deste .então, quando obtivermos os favoritos,
então vamos verificar, se (! favoritos).
Então, se não houver favoritos para este usuário,
então, obviamente, o prato que estamos verificando não existe.
Então vamos retornar, Res.StatusCode, 200.
SetHeader ('Content-Type
'' application/json ').
E então retornaremos,
dizendo, “existe”: falso.
Então o que estamos especificando aqui é que se o get é feito
para este endpoint com um DishID, esta bandeira existe aqui
será definida como true se este prato é parte dos meus favoritos.
Se este prato não faz parte dos meus favoritos, vou definir a bandeira existe como false.
Então aqui, você vê que uma vez que eu não tenho nenhum favorito, então
existe deve ser automaticamente falso neste ponto.
Então vamos dizer “existe”: falso, e então retornaremos os favoritos, aqui.
Bem, obviamente, neste caso,
os favoritos seriam nulos neste momento, caso contrário.
Então, o que significa que os favoritos não é nulo, então vamos dizer se,
(favorites.dish.indexOf),
então vamos estar procurando por req.params.
DisHid, então vamos procurar isso.
Favorites.dishes.Array, para ver se o prato existe lá.
E se não existir, obviamente isso retornará um índice negativo aqui.
Então, nesse caso também, retornarei exatamente o mesmo que aqui.
Então, se ele retorna um índice negativo,
então isso significa que, mesmo que este usuário em particular tenha um favorito central.
Este prato específico não existe na lista o
seu favorito, então é por isso que ele vai voltar existir falso aqui.
Agora, caso contrário, isso significa que o prato existe na lista de favoritos.
Então, neste caso, eu retornarei o código de status 200 existe é verdadeiro.
Assim, quando o usuário executa uma operação get
neste ponto final com o /Favorite/dishid.
Onde o DishID é fornecido como o parâmetro aqui.
Como o parâmetro records aqui,
então vamos verificar se esse prato existe nos favoritos.
Se nenhum dos favoritos existir para este usuário, em seguida, vamos retornar um existe false.
Da mesma forma, se os favoritos existem,
mas esse prato particular não existe nos favoritos, então ele retornará um falso.
Caso contrário, ele retornará um verdadeiro.
Então esta bandeira existe pode ser usado pelo meu cliente
para verificar se este prato é parte da lista de pratos favoritos para este usuário ou não.
Finalmente vamos atualizar o arquivo users.js.
Agora, no arquivo users.js, precisamos adicionar em
outro campo roteador.options aqui porque
às vezes uma solicitação Post como você viu com o login,
vamos enviar as opções primeiro para verificar, especialmente com carros,
se a solicitação de postagem será permitida.
Então é por isso que eles vão verificar carros, carros com opções aqui e depois.
Nós simplesmente retornaremos
uma mensagem de status de 200 em resposta a isso.
Então, para qualquer endpoint sob usuários, se recebemos
as opções simplesmente retornará um status 200 aqui.
Agora a função Login que tínhamos implementado anteriormente.
Nós simplesmente fizemos passport.authenticate ('local') aqui e
, em seguida, verificamos para os valores restantes aqui.
Agora este passport.authenticate ('local'), se o usuário não for
autenticado, ele simplesmente retorna um não autorizado na mensagem de resposta.
Agora isso pode não ser muito significativo para
o lado do cliente exibir essas informações.
É por isso que vamos melhorar este método de pós-login do roteador de
modo que a autenticação retorne informações mais significativas nesta parte.
Então, para fazer isso, não vamos fazer a
autenticação do passaporte aqui dentro.
Em vez disso, vamos tomar, então deixe-me remover isso de lá,
e então você vai ver como eu vou atualizar a postagem do roteador aqui.
Então vamos ver CarsWithOptions.
E então vamos incluir o req, res e o próximo aqui.
E dentro da requisição, res, e a
seguir aqui, passaporte. Authenticate,
chamaremos isso com “local”.
Agora, quando chamamos isso com local, se
ocorrer um erro de autenticação, o passport.authenticate pode ser feito para retornar o valor do erro,
e também ele retornará o usuário se não houver nenhum erro.
E ele poderia parâmetro chamado info,
que irá levar informações adicionais que podem ser passadas de volta para o usuário.
Esse erro será retornado quando houver um erro genuíno que ocorre
no possível para autenticar.
Mas se as informações do usuário são enviadas para passport.authenticate, mas
o usuário não existe, então isso não é contado como um erro.
Em vez disso, ele será contado como o usuário não existe.
E essa informação é passada de volta no objeto info que entra.
Portanto, o erro será retornado quando houver um erro genuíno que ocorre durante
o processo de autenticação.
Mas as informações, eles conterão informações se o usuário não existir e, portanto,
o passport.authenticate está passando de volta uma mensagem dizendo que o usuário não
existe ou que o nome de usuário está incorreto ou a senha está incorreta.
E assim por diante, para que a informação seja passada, na mensagem info.
Agora, vamos ver como isso é útil para nós quando olharmos para o lado do cliente um
pouco mais tarde.
Então, nesta situação,
vamos lidar com isso da seguinte forma.
E não só isso, quando chamamos este passaporte autenticar,
também precisamos passar em um (req, res,
próximo) como essa tira de três parâmetros.
Então esta é a estrutura.
Quando você precisar chamar o passaporte autenticar,
espere que ele lhe passe informações como esta como um método de retorno de chamada aqui.
Então você também precisa fornecer este req, res próximo bem ali também.
Agora, se isso ocorrer.
Então vamos dizer se (err).
Então, se ocorrer um erro,
diremos retorno próximo (err) e deixar que o
manipulador de erros do nosso roteador expresso cuide disso.
Agora, vamos considerar outras situações.
Se (! usuário), então se chegamos a este ponto, então isso significa que
não foi um erro que ocorreu, mas em vez disso, talvez o usuário não pôde ser encontrado.
Se o usuário não for encontrado, então o usuário aqui será definido como null neste caso.
Então, nessa situação, se o usuário não existir,
então precisamos ser capazes de passar informações de volta para o lado do servidor.
Então o que vamos fazer é passar essa informação neste formato,
então eu vou cortar isso daqui, e
então colá-lo aqui e então vamos editar isso.
Se o usuário é nulo, então vamos enviar de volta um
StatusCode de 401 o que significa não autorizado, e
então vamos enviar de volta sucesso informações, false.
E então não passaremos o token, passaremos a mensagem de status.
Então, aqui vamos dizer login, Sem sucesso.
E então a terceira informação passará essa informação,
esse objeto que recebemos aqui como a terceira parte da
mensagem de resposta que enviamos de volta do nosso servidor aqui.
Assim, o sinalizador de sucesso será redefinido para false.
O status será definido Login Inbem-sucedido e as informações de erro,
que são transmitidas nas informações serão repassadas.
Agora observe que essa situação ocorrerá se o nome de usuário e
a senha estiverem incorretos.
E, portanto, isso não é um erro, no sentido do erro, mas o fato de que a autenticação
não conseguiu encontrar o usuário ou a senha do usuário está incorreto.
Então essa informação será codificada no fluxo de entrada que entra, e
assim eu vou passar de volta como um erro para o lado do meu cliente.
Caso contrário, parte é
tratada como Req.Login.
Então, se isso for bem-sucedido,
o passport.authenticate adicionará esse método chamado req.Login ao usuário.
Então, neste ponto, vamos apenas passar no objeto de usuário que obtivemos.
Então aqui, se chegamos a este ponto,
então isso significa que o objeto do usuário não é nulo e
também nenhum erro ocorreu, então isso significa que
o usuário pode ser logado e assim vamos dizer err.
Então, ele tentará fazer login no usuário.
Então vamos dizer se errar.
E então passaremos o mesmo tipo de informação de erro que fizemos aqui.
Então, neste caso, se o erro. Em
caso de erro, passaremos de volta o código de status 401 e
diremos que o sucesso é falso e o status é Login sem êxito.
E, em seguida, as informações de erro que
passaremos isso como em vez de
informações que passaremos não pôde fazer login usuário.
Então essa é a mensagem que passará aqui, se o erro ocorrer.
Caso contrário, estaríamos aqui embaixo.
E assim, neste ponto, seríamos capazes de gerar o token.
Então, se chegamos até este ponto isso significa que o usuário fez
login com sucesso e assim podemos agora gerar o token.
Então vamos gerar o token com base no ID do usuário e
, em seguida, vamos passar de volta esse token de volta para o usuário.
Então, aqui vamos dizer var token.
E então podemos dizer Res.statusCode = 200 e, em seguida, res.json (sucesso) é verdadeiro, o
que significa que o usuário logado com sucesso.
E assim o status seria Login bem-sucedido e, em
seguida, a terceira parte em vez do erro, passarei o token de volta para o usuário.
Então, vamos dizer token, token,
este token que acabamos de obter anteriormente, de modo que para token será passado
como a propriedade token da mensagem de luz rip.
Então, aqui, observe que este eixo está definido como verdadeiro.
Então, o que significa que o usuário logou com sucesso.
E assim o usuário pode avançar neste ponto.
E isso tem que ser feito dentro do Req.Login aqui.
Então, neste ponto, vamos fechar o Req.Login.
Então note que isso está dentro deste Req.Login aqui.
Então lá dentro vamos passar esses três de volta.
Então deixe-me apenas recuar três linhas em.
E assim é como nós lidaríamos com o login dos usuários.
Então, novamente, revisando este código mais uma vez.
Então vamos fazer postagem de roteador, mas
em vez de fazer autenticação de passaporte ali mesmo, vamos dizer req, res,
em seguida, dentro aqui vamos fazer um passport.authenticate para o local.
E esta autenticação passará de volta, para que possamos fornecer uma função de retorno de chamada para isso.
E essa função de retorno de chamada retornará o erro, o usuário ou
as informações aqui.
E assim, se ele fizer um erro, vamos apenas permitir que o manipulador
de erros expresso para cuidar disso.
Se o usuário for nulo, isso significa que o logon do usuário não teve êxito,
e a razão para isso estará nas informações para que passará de volta como
o erro de informações na mensagem de plano aqui.
Se chegarmos a este ponto, o usuário é verificado com sucesso.
Então, vamos fazer login no usuário.
Assim, o passport.authenticate irá adicionar neste método chamado Login para
a mensagem de solicitação, para que possamos chamar o login com o usuário e
se isso retornar um erro, então vamos retornar o erro aqui adequadamente.
Se não, então teríamos chegado ao ponto em que o usuário é
autenticado com sucesso para que ele possa gerar o token da Web JSON aqui e retornar o
token da Web JSON ao usuário para confirmar se o usuário está registrado com êxito.
Então esse é o conjunto de passos que vamos usar aqui.
Agora, a razão pela qual eu faço uma maneira mais elaborada de lidar com isso é que eu quero
distinguir entre a situação em que um erro genuíno ocorre durante
o processo de aplicação, em oposição à situação em que o nome de usuário é inválido,
ou a senha é inválida.
Então esses dois casos serão tratados por esta situação em que a informação vai
levar a informação de volta para nós.
Então isso não é um erro perse, mas isso é uma situação em que
o usuário não é um usuário válido ou a senha do usuário não é válida.
Então é assim que eles vão lidar com o processo de login do usuário.
Além disso, vou adicionar em mais um método aqui chamado,
CheckJWToken.
É bem possível que, enquanto o cliente efetuou login e
obteve o token da Web JSON, algum tempo mais tarde, o JSON Web Token pode expirar.
Portanto, se o usuário tentar acessar do lado do cliente com um token expirado
para o servidor, o servidor não será capaz de autenticar o usuário.
Então, em intervalos periódicos, podemos querer cruzar a verificação para ter certeza de que o
token da web JSON ainda é válido.
Então, essa é a razão pela qual eu estou incluindo outro endpoint chamado
CheckJWTToken, por isso, se você fizer um chegar ao CheckJWTToken.
Ao incluir o token no cabeçalho de autorização
, essa chamada retornará um verdadeiro ou falso para indicar
se o token da Web JSON ainda é válido ou não.
Se não for válido, o lado do cliente pode iniciar outro login para Para que
o usuário obtenha um novo token da Web JSON, se necessário.
Então, para fazer isso, vamos dizer cors, corsWithOptions e,
req, res, aqui, como esperado.
E aqui vamos dizer,
passport.authenticate ('jwt',
E, {session: false}).
E isso iria retornar err, usuário, informações.
Lembre-se de como usamos o autenticador do Passaporte mais cedo.
Então a sessão JWT cai aqui.
Então, mais cedo aqui dizemos, passaporte.autenticar local.
Então isso é para a autenticação local.
Então isso é para a autenticação de token da Web JSON.
Então, quando chamamos isso, então, uma vez que isso vai verificar o token da web JSON,
então eu vou dizer, se (err), retornar próximo (err).
E, em seguida, deixe o manipulador de erros Express cuidar dessa situação.
E então vamos dizer, se (! usuário),
Se o usuário não existir, então da mesma forma, senão.
Então, o que significa que se o objeto de usuário foi encontrado a partir do token da Web JSON e
depois carregado no req.user, isso significa que o usuário é um usuário válido.
E assim pode ser permitido avançar.
Caso contrário, vamos dizer que o usuário não existe.
Então precisamos inferir que o token da web JSON expirou.
Então, neste ponto, enviaremos uma reserva com o código de status de,
401, então não autorizado.
SetHeader (, 'Content-Type',
'application/json').
E então vamos retornar res,
.json, vamos dizer, {status:,
'JWT invalid! '.
E então devolveremos uma bandeira chamada sucesso: falso.
E, em seguida, Vamos retornar as informações que
obtemos se o usuário não é autenticado como o erro neste ponto.
Caso contrário, isso significa que chegamos a este ponto quando o usuário é um usuário válido.
Então, neste caso, deixe-me apenas copiar esse código aqui,
estaremos enviando um código de status de 200, e
então o res.json enviará JWT,
válido! , e o sucesso será verdadeiro.
E a terceira parte, enviaremos as informações do usuário.
Dessa forma, quando esse endpoint é chamado
com o método get, então isso verificará se o token é válido ou não.
Se o token for válido, você receberá esta resposta.
E a partir do sinalizador de sucesso na resposta,
você pode verificar se o token da Web JSON é válido ou não.
E isso é útil no lado do cliente.
Agora este passaporte aqui, passaporte.autenticar aqui,
terá que ser fornecido com req e res como os dois parâmetros aqui.
Então é assim que chamamos esse passaporte. Autenticar.
Observe que sempre que você chamar passport.authenticate e
esperar essa função de retorno de chamada aqui, você precisa anexar este ponto, req,
.res, a esse passport.authenticate e, em seguida, de volta aqui.
Então, com isso, nós atualizamos tudo no lado do servidor.
Então vamos salvar todas as alterações no lado do servidor.
Então agora o nosso servidor está pronto para
lidar com os pedidos recebidos do nosso cliente Angular.
Com isso, completamos este exercício.
Neste exercício, preparamos nosso servidor Express para
lidar com solicitações recebidas de nosso cliente Angular.
No próximo exercício, vamos olhar para o cliente Angular com mais detalhes para
entender como ele está se comunicando com este servidor extra.
Este é um bom momento para você fazer um commit Git com a mensagem,
integrando cliente e servidor.
[ MUSIC]