{"id":21541704,"url":"https://github.com/concretesolutions/desafio-java","last_synced_at":"2026-01-03T18:03:53.781Z","repository":{"id":46232548,"uuid":"54932544","full_name":"concretesolutions/desafio-java","owner":"concretesolutions","description":null,"archived":false,"fork":false,"pushed_at":"2021-02-05T17:45:21.000Z","size":8,"stargazers_count":26,"open_issues_count":0,"forks_count":37,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-01-24T08:31:16.576Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/concretesolutions.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-03-29T00:13:45.000Z","updated_at":"2024-11-18T15:15:22.000Z","dependencies_parsed_at":"2022-07-26T05:16:35.299Z","dependency_job_id":null,"html_url":"https://github.com/concretesolutions/desafio-java","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/concretesolutions%2Fdesafio-java","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/concretesolutions%2Fdesafio-java/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/concretesolutions%2Fdesafio-java/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/concretesolutions%2Fdesafio-java/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/concretesolutions","download_url":"https://codeload.github.com/concretesolutions/desafio-java/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244124179,"owners_count":20401683,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-24T05:07:20.830Z","updated_at":"2026-01-03T18:03:48.748Z","avatar_url":"https://github.com/concretesolutions.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# Desafio Java Concrete Solutions\n\nCrie uma aplicação que exponha uma API RESTful de criação de usuários e login.\n\nO desafio consiste em uma jornada de usuário, onde:\n1. O usuário deverá se cadastrar\n2. Uma vez cadastrado, o usuário deverá conseguir fazer login\n3. Ao fazer login, o usuário deverá ter um token e poderá utilizar esse token para acessar o seu perfil\n\n## Requisitos\n\n* Utilizar JSON como media type em todos os endpoints, inclusive os de erro.\n* Banco de dados em memória, pode ser HSQLDB, H2 etc...\n* Persistência com Hibernate.\n* Framework Spring Boot.\n* Prazo de 4 dias corridos.\n* Entregar um repo público (github ou bitbucket) com o código fonte.\n* Java 7+.\n\nTodas as mensagens de erro devem ter o formato:\n\u003e\n\u003e```json\n\u003e    {\"mensagem\": \"mensagem de erro\"}\n\u003e```\n\n## Requisitos desejáveis\n\n* JWT como token.\n* Testes unitários.\n* Utilizar processo de build via gradle.\n* Criptogafia não reversível (hash) na senha e no token.\n* Entregar a API rodando em algum host (Heroku, AWS, etc) na porta 80 ou 443.\n\n## Cadastro\nEste endpoint deverá ser utilizado para cadastrar um novo usuário na base, seguindo as especificações abaixo:\n\n* 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:\n\nExemplo:\n\n\u003e```json\n\u003e   {\n\u003e        \"name\": \"João da Silva\",\n\u003e        \"email\": \"joao@silva.org\",\n\u003e        \"password\": \"hunter2\",\n\u003e        \"phones\": [\n\u003e            {\n\u003e                \"number\": \"987654321\",\n\u003e                \"ddd\": \"21\"\n\u003e            }\n\u003e        ]\n\u003e    }\n\u003e```\n\n* Responder o código de status HTTP apropriado.\n  \n* Em caso de sucesso, retorne no body de resposta, o usuário, mais os campos:\n    * `id`: id do usuário (pode ser o próprio gerado pelo banco, porém seria interessante se fosse um UUID)\n    * `created`: data da criação do usuário\n    * `modified`: data da última atualização do usuário\n    * `last_login`: data do último login (no caso da criação, será a mesma data que a  data de criação)\n    * `token`: token de acesso para o endpoint de perfil (pode ser um UUID ou um JWT)\n\nExemplo:\n\n\u003e```json\n\u003e    {   \n\u003e        \"id\": \" 00c6de58-6582-11eb-ae93-0242ac130002\",\n\u003e         \"name\": \"João da Silva\",\n\u003e         \"email\": \"joao@silva.org\",\n\u003e         \"password\": \"hunter2\",\n\u003e         \"phones\": [\n\u003e             {\n\u003e                 \"number\": \"987654321\",\n\u003e                 \"ddd\": \"21\"\n\u003e             }\n\u003e         ],\n\u003e         \"created\": \"2020-10-03T19:30:00\",\n\u003e         \"modified\": \"2020-10-03T19:30:00\",\n\u003e         \"last_login\": \"2020-10-03T19:30:00\",\n\u003e         \"token\": \"eyJhbGciOiJIUzUxMiJ9.eyJwcm9ncmFtQ29kZSI6ImRhMjhiNjk4MDM0M2I3ZjE3ODUwMDgyNzlmNzI0MGJiNWNmZDAyNjYiLCJ1c2VySWQiOiI1ZjkyZGI3Y2M3MDgxYjliOTZmNGNlNDkiLCJwZXJzb25JZCI6IjVmOTJkYjdjYzcwODFiOWI5NmY0Y2U0OSIsInVzZXJUeXBlIjoiQUNDT1VOVCIsInNlc3Npb25JZCI6Ijc1NWM0MTcyLWYyYjgtNDRiYS1hMzgzLTBlZGI2NzdlYTZiYyIsInJvbGVzIjoiIiwic3ViIjoiNjk0MjA2NjMwMzUiLCJhdWQiOiJ1bmtub3duIiwiaWF0IjoxNjA3NTM0MzU1LCJleHAiOjE2MDc1MzQ1MzV9.3GNRIE4ND_NSbe7cDYoVRUMMXj-_sZmwE_oX-u6Ju7xnUYipEjKz1A2m7mUfPa08BY3USe5zau220u0Zij3LEA\"\n\u003e     }\n\u003e ```\n\n* Caso o e-mail já exista, deverá retornar erro com a mensagem \"E-mail já existente\".\n  \n* O token deverá ser persistido junto com o usuário.\n\n## Login \n\nEste 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.\n\n* Utilizar o exemplo abaixo para o body:\n\n\u003e ```json\n\u003e     {\n\u003e         \"email\": \"joao@silva.org\",\n\u003e         \"password\": \"hunter2\"\n\u003e     }\n\u003e ```\n\n* Caso o e-mail e a senha correspondam a um usuário existente, retornar com o status apropriado e conforme o exemplo abaixo:\n  \n\u003e```json\n\u003e    {   \n\u003e        \"id\": \" 00c6de58-6582-11eb-ae93-0242ac130002\",\n\u003e         \"name\": \"João da Silva\",\n\u003e         \"email\": \"joao@silva.org\",\n\u003e         \"password\": \"hunter2\",\n\u003e         \"phones\": [\n\u003e             {\n\u003e                 \"number\": \"987654321\",\n\u003e                 \"ddd\": \"21\"\n\u003e             }\n\u003e         ],\n\u003e         \"created\": \"2020-10-03T19:30:00\",\n\u003e         \"modified\": \"2020-10-03T19:30:00\",\n\u003e         \"last_login\": \"2020-10-03T19:30:00\",\n\u003e         \"token\": \"eyJhbGciOiJIUzUxMiJ9.eyJwcm9ncmFtQ29kZSI6ImRhMjhiNjk4MDM0M2I3ZjE3ODUwMDgyNzlmNzI0MGJiNWNmZDAyNjYiLCJ1c2VySWQiOiI1ZjkyZGI3Y2M3MDgxYjliOTZmNGNlNDkiLCJwZXJzb25JZCI6IjVmOTJkYjdjYzcwODFiOWI5NmY0Y2U0OSIsInVzZXJUeXBlIjoiQUNDT1VOVCIsInNlc3Npb25JZCI6Ijc1NWM0MTcyLWYyYjgtNDRiYS1hMzgzLTBlZGI2NzdlYTZiYyIsInJvbGVzIjoiIiwic3ViIjoiNjk0MjA2NjMwMzUiLCJhdWQiOiJ1bmtub3duIiwiaWF0IjoxNjA3NTM0MzU1LCJleHAiOjE2MDc1MzQ1MzV9.3GNRIE4ND_NSbe7cDYoVRUMMXj-_sZmwE_oX-u6Ju7xnUYipEjKz1A2m7mUfPa08BY3USe5zau220u0Zij3LEA\"\n\u003e     }\n\u003e ```\n\n* 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\".\n\n* 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\".\n\n## Perfil do Usuário\n\nEste endpoint deverá receber no header um token (jwt ou uuid), e um id de usuário no path, considerar os cenários a seguir:\n\n* Caso o token não seja passado no header, deverá retornar erro com status apropriado e com a mensagem \"Não autorizado\".\n\n* Caso o token seja diferente do persistido, retornar erro com status apropriado e com a mensagem \"Não autorizado\".\n  \n* Caso o token exista, e seja o mesmo persistido, buscar o usuário pelo `id` passado no path.\n\n* Caso o usuário não seja encontrado pelo id, retornar com status e mensagem de erro apropriados.\n\n* Verificar se o último login foi há MENOS de 30 minutos atrás. \n     * Caso não seja há MENOS de 30 minutos atrás, retornar erro com status apropriado e com a mensagem \"Sessão inválida\".\n  \n* Caso tudo esteja ok, retornar conforme o exemplo abaixo:\n  \n\u003e```json\n\u003e    {   \n\u003e        \"id\": \" 00c6de58-6582-11eb-ae93-0242ac130002\",\n\u003e        \"name\": \"João da Silva\",\n\u003e        \"email\": \"joao@silva.org\",\n\u003e        \"password\": \"hunter2\",\n\u003e        \"phones\": [\n\u003e            {\n\u003e                \"number\": \"987654321\",\n\u003e                \"ddd\": \"21\"\n\u003e            }\n\u003e        ],\n\u003e        \"created\": \"2020-10-03T19:30:00\",\n\u003e        \"modified\": \"2020-10-03T19:30:00\",\n\u003e        \"last_login\": \"2020-10-03T19:30:00\",\n\u003e        \"token\": \"eyJhbGciOiJIUzUxMiJ9.eyJwcm9ncmFtQ29kZSI6ImRhMjhiNjk4MDM0M2I3ZjE3ODUwMDgyNzlmNzI0MGJiNWNmZDAyNjYiLCJ1c2VySWQiOiI1ZjkyZGI3Y2M3MDgxYjliOTZmNGNlNDkiLCJwZXJzb25JZCI6IjVmOTJkYjdjYzcwODFiOWI5NmY0Y2U0OSIsInVzZXJUeXBlIjoiQUNDT1VOVCIsInNlc3Npb25JZCI6Ijc1NWM0MTcyLWYyYjgtNDRiYS1hMzgzLTBlZGI2NzdlYTZiYyIsInJvbGVzIjoiIiwic3ViIjoiNjk0MjA2NjMwMzUiLCJhdWQiOiJ1bmtub3duIiwiaWF0IjoxNjA3NTM0MzU1LCJleHAiOjE2MDc1MzQ1MzV9.3GNRIE4ND_NSbe7cDYoVRUMMXj-_sZmwE_oX-u6Ju7xnUYipEjKz1A2m7mUfPa08BY3USe5zau220u0Zij3LEA\"\n\u003e    }\n\u003e```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fconcretesolutions%2Fdesafio-java","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fconcretesolutions%2Fdesafio-java","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fconcretesolutions%2Fdesafio-java/lists"}