A empresa que você trabalha precisa criar um MVP (Minimum Viable Product) de uma API que faz o controle de usuários através de um CRUD. Essa API também precisa ter um controle de acessos, onde alguns recursos podem ser acessados apenas por usuários que fizeram login na aplicação, e outros recursos apenas usuários que fizeram login e tem permissões de administrador podem acessar.
Você foi o desenvolvedor selecionado para implementar o MVP levando em conta o que está sendo requisitado a seguir.
A entrega deve seguir as seguintes regras:
- O código deve estar em TypeScript, caso não esteja a entrega será zerada;
- Deverá ser utilizado um banco de dados postgres para a elaboração da API;
- O nome da tabela, das colunas e demais especificações, devem ser seguidas à risca. Caso tenha divergência, será descontado nota;
- Tenha muita atenção sobre o nome das chaves nos objetos de entrada e saída de cada requisição;
- Na raiz do diretório deve-se conter uma pasta nomeada sql, com dois arquivos:
- createTables.sql: contendo as queries de criação e inserção das tabelas;
- diagram.png/jpg: um arquivo .png ou .jpg contendo o diagrama da tabela;
- caso o arquivo createTables.sql não exista, a entrega será zerada.
Essa entrega possui testes automatizados, portanto:
- Caso o subdiretório sql e o arquivo createTables.sql não estejam com os nomes corretos ou no caminho correto os testes falharão, pois não será possível encontrar as queries a serem executadas;
- Caso o nome de alguma tabela, tipo ou coluna não esteja de acordo com o esperado, os testes também falharão.
- A organização dos demais arquivos e pastas deve seguir o que foi visto previamente.
- Para que os testes possam ser executados, existe um script de limpeza do banco que utiliza as queries do arquivo createTables.sql, por isso é importante seguir as orientações sobre o subdiretório sql e seus arquivos à risca.
Método | Endpoint | Responsabilidade |
---|---|---|
POST | /users | Cadastrar um novo usuário |
POST | /login | Logar com um usuário na aplicação gerando um token. |
GET | /users | Listar todos os usuários da aplicação |
GET | /users/profile | Listar um usuário que está logado na aplicação |
PATCH | /users/:id | Atualizar os dados de um usuário |
DELETE | /users/:id | Fazer um soft delete de um usuário |
PUT | users/:id/recover | Reativar um usuário |
Deve ser criado um banco de dados em PostgreSQL com uma tabelas que irá armazenar os dados das requisições. Essa tabela deve seguir as seguintes orientações:
-
Nome da tabela: users
-
Colunas:
- id: inteiro, sequencial e chave primária.
- name: string, tamanho máximo de 20 e obrigatório.
- email: string, tamanho máximo de 100, único e obrigatório.
- password: string, tamanho máximo de 120 e obrigatório..
- admin: booleano, obrigatório e falso por padrão.
- active: booleano, obrigatório e verdadeiro por padrão
- Nas rotas POST e PATCH, é necessário serializar os dados de entrada utilizando o zod;
- Chaves incorretas devem ser ignoradas caso enviadas.
- Na rota POST /users as chaves de name, email e password são obrigatórias.
- Na rota POST /users, as chaves id e active não devem ser enviadas e devem ser ignoradas pelo zod.;
- Esses dados devem ser gerados de forma automática pela aplicação.
- Na rota POST /users a chave de admin é opcional.
- Caso não enviado, o dado será gerado de maneira automática pelo banco.
- Na rota PATCH /users, as chaves id, admin e active não podem ser atualizadas.
- Caso sejam enviadas devem ser ignoradas;
- A senha não deve ser retornada em nenhuma das rotas do serviço;
Todas as regras devem ser feitas através de middlewares;
-
O email deve ser único:
-
Caso seja enviado um email já registrado o retorno deve ser exatamente o abaixo:
Resposta do servidor: Body: Formato Json Status code: 409 CONFLICT { "message": "E-mail already registered" }
-
-
Deve haver serialização de dados:
-
A serialização dos dados de entrada deve ser feita utilizando o zod.
-
Em caso de erro a mensagem retornada deve seguir o padrão a seguir:
Resposta do servidor: Body: Formato Json Status code: 400 BAD REQUEST { "name": ["Required"], "email": ["Invalid email"], "password": ["Expected string, received number"] }
-
-
Devem conter validação por token:
-
Caso o token não seja enviado, deve se obter o seguinte retorno:
Resposta do servidor: Body: Formato Json Status code: 401 UNAUTHORIZED { "message": "Missing Bearer Token" }
-
Caso haja um erro na decodificação do token JWT, deve-se retornar a mensagem de erro padrão da biblioteca, nos parâmetros abaixo:
Resposta do servidor: Body: Formato Json Status code: 401 UNAUTHORIZED { "message": // mensagem padrão da biblioteca }
-
-
Apenas administradores podem acessar:
-
Caso um usuário não administrador faça requisição, deve-se obter o seguinte retorno:
Resposta do servidor: Body: Formato Json Status code: 403 FORBIDDEN { "message": "Insufficient Permission" }
-
-
Tanto usuários administradores quanto não administradores podem fazer requisições:
-
Um usuário não administrador só pode atualizar ou deletar a sí mesmo;
-
Um usuário administrador pode atualizar ou deletar qualquer usuário;
-
Caso um usuário não administrador tente deletar ou atualizar outro usuário que não seja o dele, deve-se obter o seguinte retorno:
Resposta do servidor: Body: Formato Json Status code: 403 FORBIDDEN { "message": "Insufficient Permission" }
-
-
Deve validar se o usuário:
-
Existe (email valido);
-
Está ativo;
-
Se a senha está correta.
-
Caso não passe em alguma das validações anteriores deve-se obter o seguinte retorno:
Resposta do servidor: Body: Formato Json Status code: 401 UNAUTHORIZED { "message": "Wrong email/password" }
-
-
Deve reativar um usuário que está inativo:
-
O valor de active deve ser alterado para true;
-
Caso o active do usuário com o id enviado na rota já seja true, deve-se retornar o seguinte:
Resposta do servidor: Body: Formato Json Status code: 400 BAD REQUEST { "message": "User already active" }
-
-
Deve verificar se o id passado existe:
-
Caso o usuário do id passado não exista deverá retornar o seguinte:
Resposta do servidor: Body: Formato Json Status code: 404 NOT FOUND { "message": "User not found" }
Essas rotas não precisam de um token válido para serem acessadas.
-
POST /users
-
Rota de criação de usuário. A chave admin é opcional, caso não enviada deve ser definida como false.
Dados de Envio: Body: Formato Json { "name": "Fabio", "email": "[email protected]", "password": "naomaisjunior", "admin": true, "active": false }
Resposta do servidor: Body: Formato Json Status code: 201 CREATED // atente-se ao valor de active recebido e retornado; { "id": 1, "name": "Fabio", "email": "[email protected]", "admin": true, "active": true }
-
-
POST - /login
-
Deve ser capaz de gerar um token jwt válido.
Dados de Envio: Body: Formato Json { "email": "[email protected]", "password": "naomaisjunior" }
Resposta do servidor: Body: Formato Json Status code: 200 OK { "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." }
-
Todas as rotas a seguir devem ser autenticas.
No header(cabeçalho) da requisição deve ser enviado um Bearer <token>.
Header |
---|
Option: Authorization |
Type: Bearer |
Value: JWT token |
{
"Authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI..."
}
-
GET - /users
-
Rota de listagem de usuários;
-
Deve retornar todos os usuários da aplicação.
Resposta do servidor: Body: Formato Json Status code: 200 OK [ { "id": 1, "name": "Fabio", "email": "[email protected]", "admin": true, "active": true }, { "id": 2, "name": "Cauan", "email": "[email protected]", "admin": false, "active": false } ]
-
-
GET - /users/profile
-
Rota de perfil. Deve retornar todos os dados dos usuário logado.
Resposta do servidor: Body: Formato Json Status code: 200 OK { "id": 1, "name": "Fabio", "email": "[email protected]", "admin": true, "active": true }
-
-
PATCH - /users/:id
-
Rota de atualização de usuário. Deve ser capaz de atualizar tanto um quanto todos os dados de um usuário.
-
O exemplo abaixo foi feito na rota /users/1.
Dados de Envio: Body: Formato Json { "name": "Fabio Junior" }
Resposta do servidor: Body: Formato Json Status code: 200 OK { "id": 1, "name": "Fabio Junior", "email": "[email protected]", "admin": true, "active": true }
-
-
DELETE - /users/:id
-
Deve ser capaz de fazer soft delete em um usuário;
O soft delete é a ação de modificar alguma propriedade de uma tabela que indica que o dado está ativo ou não, nesse caso é a propriedade active da tabela de users, na qual é possível identificar que o mesmo foi "marcado" como deletado, mas suas informações ainda irão permanecer no banco. Sendo uma modificação em vez deleção.
-
O exemplo abaixo foi feito na rota /users/2
Resposta do servidor: Body: Nenhum Status code: 204 NO CONTENT // nenhum dado deve ser retorando
-
-
PUT - /users/:id/recover
-
Deve ser capaz de recuperar o usuário que foi desativado.
-
O active deve ser alterado para true.
-
O exemplo abaixo foi feito na rota /users/2/recover.
Resposta do servidor: Body: Formato Json Status code: 200 OK { "id": 2, "name": "Cauan", "email": "[email protected]", "admin": false, "active": true }
-