Crie uma aplicação que exponha uma API RESTful de criação de usuários e login.
O desafio consiste em uma jornada de usuário, onde:
- O usuário deverá se cadastrar
- Uma vez cadastrado, o usuário deverá conseguir fazer login
- Ao fazer login, o usuário deverá ter um token e poderá utilizar esse token para acessar o seu perfil
- Utilizar JSON como media type em todos os endpoints, inclusive os de erro.
- Banco de dados em memória, pode ser HSQLDB, H2 etc...
- Persistência com Hibernate.
- Framework Spring Boot.
- Prazo de 4 dias corridos.
- Entregar um repo público (github ou bitbucket) com o código fonte.
- Java 7+.
Todas as mensagens de erro devem ter o formato:
{"mensagem": "mensagem de erro"}
- JWT como token.
- Testes unitários.
- Utilizar processo de build via gradle.
- Criptogafia não reversível (hash) na senha e no token.
- Entregar a API rodando em algum host (Heroku, AWS, etc) na porta 80 ou 443.
Este endpoint deverá ser utilizado para cadastrar um novo usuário na base, seguindo as especificações abaixo:
- Esse endpoint deverá receber no body um usuário com os campos "nome", "email", "senha", mais uma lista de objetos "telefone", seguindo o formato abaixo:
Exemplo:
{ "name": "João da Silva", "email": "[email protected]", "password": "hunter2", "phones": [ { "number": "987654321", "ddd": "21" } ] }
-
Responder o código de status HTTP apropriado.
-
Em caso de sucesso, retorne no body de resposta, o usuário, mais os campos:
id
: id do usuário (pode ser o próprio gerado pelo banco, porém seria interessante se fosse um UUID)created
: data da criação do usuáriomodified
: data da última atualização do usuáriolast_login
: data do último login (no caso da criação, será a mesma data que a data de criação)token
: token de acesso para o endpoint de perfil (pode ser um UUID ou um JWT)
Exemplo:
{ "id": " 00c6de58-6582-11eb-ae93-0242ac130002", "name": "João da Silva", "email": "[email protected]", "password": "hunter2", "phones": [ { "number": "987654321", "ddd": "21" } ], "created": "2020-10-03T19:30:00", "modified": "2020-10-03T19:30:00", "last_login": "2020-10-03T19:30:00", "token": "eyJhbGciOiJIUzUxMiJ9.eyJwcm9ncmFtQ29kZSI6ImRhMjhiNjk4MDM0M2I3ZjE3ODUwMDgyNzlmNzI0MGJiNWNmZDAyNjYiLCJ1c2VySWQiOiI1ZjkyZGI3Y2M3MDgxYjliOTZmNGNlNDkiLCJwZXJzb25JZCI6IjVmOTJkYjdjYzcwODFiOWI5NmY0Y2U0OSIsInVzZXJUeXBlIjoiQUNDT1VOVCIsInNlc3Npb25JZCI6Ijc1NWM0MTcyLWYyYjgtNDRiYS1hMzgzLTBlZGI2NzdlYTZiYyIsInJvbGVzIjoiIiwic3ViIjoiNjk0MjA2NjMwMzUiLCJhdWQiOiJ1bmtub3duIiwiaWF0IjoxNjA3NTM0MzU1LCJleHAiOjE2MDc1MzQ1MzV9.3GNRIE4ND_NSbe7cDYoVRUMMXj-_sZmwE_oX-u6Ju7xnUYipEjKz1A2m7mUfPa08BY3USe5zau220u0Zij3LEA" }
-
Caso o e-mail já exista, deverá retornar erro com a mensagem "E-mail já existente".
-
O token deverá ser persistido junto com o usuário.
Este endpoint deverá ser utilizado para que o usuário, utilizando um e-mail e senha cadastrados, realize um login, ao fazer login o token deverá ser atualizado.
- Utilizar o exemplo abaixo para o body:
{ "email": "[email protected]", "password": "hunter2" }
- Caso o e-mail e a senha correspondam a um usuário existente, retornar com o status apropriado e conforme o exemplo abaixo:
{ "id": " 00c6de58-6582-11eb-ae93-0242ac130002", "name": "João da Silva", "email": "[email protected]", "password": "hunter2", "phones": [ { "number": "987654321", "ddd": "21" } ], "created": "2020-10-03T19:30:00", "modified": "2020-10-03T19:30:00", "last_login": "2020-10-03T19:30:00", "token": "eyJhbGciOiJIUzUxMiJ9.eyJwcm9ncmFtQ29kZSI6ImRhMjhiNjk4MDM0M2I3ZjE3ODUwMDgyNzlmNzI0MGJiNWNmZDAyNjYiLCJ1c2VySWQiOiI1ZjkyZGI3Y2M3MDgxYjliOTZmNGNlNDkiLCJwZXJzb25JZCI6IjVmOTJkYjdjYzcwODFiOWI5NmY0Y2U0OSIsInVzZXJUeXBlIjoiQUNDT1VOVCIsInNlc3Npb25JZCI6Ijc1NWM0MTcyLWYyYjgtNDRiYS1hMzgzLTBlZGI2NzdlYTZiYyIsInJvbGVzIjoiIiwic3ViIjoiNjk0MjA2NjMwMzUiLCJhdWQiOiJ1bmtub3duIiwiaWF0IjoxNjA3NTM0MzU1LCJleHAiOjE2MDc1MzQ1MzV9.3GNRIE4ND_NSbe7cDYoVRUMMXj-_sZmwE_oX-u6Ju7xnUYipEjKz1A2m7mUfPa08BY3USe5zau220u0Zij3LEA" }
-
Caso o e-mail não exista, retornar status apropriado e utilizar o formato de mensagem de erro com a mensagem "Usuário e/ou senha inválidos".
-
Caso o e-mail exista mas a senha não bata, retornar o status 401 e utilizar o formato de mensagem de erro com a mensagem "Usuário e/ou senha inválidos".
Este endpoint deverá receber no header um token (jwt ou uuid), e um id de usuário no path, considerar os cenários a seguir:
-
Caso o token não seja passado no header, deverá retornar erro com status apropriado e com a mensagem "Não autorizado".
-
Caso o token seja diferente do persistido, retornar erro com status apropriado e com a mensagem "Não autorizado".
-
Caso o token exista, e seja o mesmo persistido, buscar o usuário pelo
id
passado no path. -
Caso o usuário não seja encontrado pelo id, retornar com status e mensagem de erro apropriados.
-
Verificar se o último login foi há MENOS de 30 minutos atrás.
- Caso não seja há MENOS de 30 minutos atrás, retornar erro com status apropriado e com a mensagem "Sessão inválida".
-
Caso tudo esteja ok, retornar conforme o exemplo abaixo:
{ "id": " 00c6de58-6582-11eb-ae93-0242ac130002", "name": "João da Silva", "email": "[email protected]", "password": "hunter2", "phones": [ { "number": "987654321", "ddd": "21" } ], "created": "2020-10-03T19:30:00", "modified": "2020-10-03T19:30:00", "last_login": "2020-10-03T19:30:00", "token": "eyJhbGciOiJIUzUxMiJ9.eyJwcm9ncmFtQ29kZSI6ImRhMjhiNjk4MDM0M2I3ZjE3ODUwMDgyNzlmNzI0MGJiNWNmZDAyNjYiLCJ1c2VySWQiOiI1ZjkyZGI3Y2M3MDgxYjliOTZmNGNlNDkiLCJwZXJzb25JZCI6IjVmOTJkYjdjYzcwODFiOWI5NmY0Y2U0OSIsInVzZXJUeXBlIjoiQUNDT1VOVCIsInNlc3Npb25JZCI6Ijc1NWM0MTcyLWYyYjgtNDRiYS1hMzgzLTBlZGI2NzdlYTZiYyIsInJvbGVzIjoiIiwic3ViIjoiNjk0MjA2NjMwMzUiLCJhdWQiOiJ1bmtub3duIiwiaWF0IjoxNjA3NTM0MzU1LCJleHAiOjE2MDc1MzQ1MzV9.3GNRIE4ND_NSbe7cDYoVRUMMXj-_sZmwE_oX-u6Ju7xnUYipEjKz1A2m7mUfPa08BY3USe5zau220u0Zij3LEA" }