Pular para conteúdo

Refinamento Sprint 2 - Gestão de usuários

Visão Geral

Stack Tecnológica

Backend (Spring Boot)

  • Framework: Spring Boot 3.x
  • Persistência: Spring Data JPA + PostgreSQL/MySQL
  • Validação: Bean Validation (Hibernate Validator)
  • Segurança: Spring Security + JWT
  • Documentação: OpenAPI 3 (Swagger)
  • Logs: Logback/SLF4J

Frontend (Next.js)

  • Framework: Next.js 14+ (App Router)
  • UI Components: React + TypeScript
  • Styling: Tailwind CSS ou Material-UI
  • State Management: React Query/TanStack Query
  • Forms: React Hook Form + Zod validation
  • HTTP Client: Axios ou Fetch API

Estrutura de Dados

Entidades Principais

  • User: Entidade base para colaboradores e PDMs
  • UserType: ENUM (COLLABORATOR, PDM)
  • UserStatus: ENUM (ACTIVE, INACTIVE)

Relacionamentos

  • User → User: Relacionamento self-referencing (PDM → Colaborador)

APIs REST

Endpoints Principais

  • GET /api/users - Lista paginada de usuários
  • POST /api/users - Criação de usuário
  • GET /api/users/{id} - Detalhes do usuário
  • PUT /api/users/{id} - Atualização de usuário
  • DELETE /api/users/{id} - Desativação de usuário
  • GET /api/users/pdms - Lista de PDMs disponíveis

Padrões

  • DTOs: Request/Response separados das entidades
  • Validation: Validação de negócio no service layer
  • Exception Handling: Global exception handler
  • Pagination: Spring Data Pageable

Componentes Frontend

Páginas/Rotas

  • /admin/users - Lista de usuários
  • /admin/users/new - Cadastro de usuário
  • /admin/users/[id]/edit - Edição de usuário

Componentes Principais

  • UserList: Tabela com paginação e ações
  • UserForm: Formulário reutilizável (create/edit)
  • UserTypeSelector: Seletor com lógica condicional
  • PDMSelector: Dropdown de PDMs disponíveis
  • ConfirmDialog: Modal de confirmação para exclusão

mmd

Entendendo o Spring Security

O Spring Security é um framework poderoso e altamente personalizável que fornece autenticação e controle de acesso para aplicações Java, especialmente aquelas construídas com o Spring Framework. Ele oferece suporte a diversos métodos de autenticação, incluindo autenticação baseada em formulário, autenticação básica, OAuth2, e JWT (JSON Web Tokens), permitindo que os desenvolvedores implementem segurança de maneira flexível e eficaz. O Spring Security também permite a definição de regras de autorização por meio de anotações, como @PreAuthorize, que facilitam o controle de acesso a métodos e recursos com base nas permissões do usuário. Além disso, o framework integra-se de forma transparente com o modelo de segurança do Spring, permitindo o gerenciamento de sessões e a proteção contra vulnerabilidades comuns, como CSRF (Cross-Site Request Forgery) e ataques de força bruta, tornando-o uma escolha popular para proteger aplicações web e APIs RESTful.

mmd

Explicação:

  1. Cliente: O ponto de entrada que faz uma requisição HTTP.
  2. OncePerRequestFilter: Um filtro que é invocado para cada requisição, garantindo que a autenticação e a autorização sejam processadas.
  3. Authentication: O objeto que contém as informações do usuário autenticado.
  4. SecurityContextHolder: Um holder que armazena o contexto de segurança da requisição atual.
  5. Verificação de Autoridade: O processo de checar se o usuário autenticado possui a autoridade necessária.
  6. @PreAuthorize: Anotação que protege métodos com base nas autoridades do usuário.
  7. Requisição Processada: Se o usuário possui a autoridade, a requisição é processada normalmente.
  8. Acesso Negado: Se o usuário não possui a autoridade, um erro de acesso negado é retornado.
  9. Configuração de Segurança: Onde as configurações do Spring Security são definidas, incluindo o gerenciamento de sessões.

Observações:

  • A configuração sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) indica que a aplicação não manterá sessões e cada requisição é independente, o que é comum em APIs RESTful.

Protegendo Endpoints com o HasType

O componente HasType é uma anotação personalizada que combina a funcionalidade do Spring Security com a flexibilidade de anotações customizadas, permitindo que métodos ou classes sejam protegidos com base nas autoridades (permissions) do usuário. Ao ser aplicada a um método ou classe, essa anotação utiliza a expressão @PreAuthorize para verificar se o usuário autenticado possui a autoridade especificada no parâmetro value. Isso proporciona um controle de acesso mais granular, permitindo que os desenvolvedores definam facilmente quais roles ou permissões são necessárias para acessar determinadas funcionalidades da aplicação, simplificando a implementação de regras de segurança e tornando o código mais legível e organizado. Assim, HasType pode ser usado para proteger endpoints ou serviços, assegurando que somente usuários com as permissões adequadas possam executá-los.

Nota

Para gestão de acesso mais granular use a annotation @PreAuthorize que permite usar expressões mais avançadas

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api/resource")
public class ResourceController {

    @GetMapping("/secure-data")
    @HasType("ADMIN") // Apenas usuários com a autoridade ROLE_ADMIN podem acessar este método
    public ResponseEntity<String> getSecureData() {
        String secureData = "Este é um dado seguro que só administradores podem acessar.";
        return ResponseEntity.ok(secureData); // Retorna o dado seguro
    }
}

Protegendo Rotas do NextJS com middlewares

A proteção baseada em middleware no Next.js é uma abordagem que permite implementar lógica de autenticação e autorização de forma centralizada, antes que as requisições cheguem às rotas específicas da aplicação. O middleware pode ser utilizado para interceptar requisições e verificar se um usuário está autenticado ou possui as permissões necessárias para acessar determinadas páginas ou recursos. Isso proporciona uma camada adicional de segurança, garantindo que apenas usuários autorizados possam acessar informações sensíveis ou ações restritas dentro da aplicação. Além disso, a utilização de middleware melhora a organização do código, uma vez que a lógica de segurança pode ser separada das funções de negócio.

mmd

Exemplo:

// middleware.js

import { NextResponse } from 'next/server';
import jwt from 'jsonwebtoken';

// Função para verificar se o usuário é ADMIN
export async function middleware(req) {
    const token = req.cookies.token; // Supondo que o token JWT está armazenado em cookies

    if (!token) {
        // Se não houver token, redirecionar para a página de login
        return NextResponse.redirect(new URL('/login', req.url));
    }

    const decoded = jwt.decode(token); // Decodifica o token sem verificar a assinatura

    // Verifica se o tipo do usuário é ADMIN
    if (!decoded || decoded.type !== 'ADMIN') {
        return NextResponse.redirect(new URL('/unauthorized', req.url)); // Redireciona para página de acesso negado
    }

    // Se o tipo for ADMIN, permite o acesso à rota
    return NextResponse.next();
}

// Configurando o middleware para as rotas /users
export const config = {
    matcher: ['/users/:path*'],
};