Explorar el Código

Authentication and layouts

Ranghetti hace 6 meses
padre
commit
9cfcacb2c8

+ 4 - 2
src/main/java/com/platform2easy/genesis/GenesisApplication.java

@@ -1,7 +1,7 @@
 package com.platform2easy.genesis;
 
 import com.platform2easy.genesis.domain.enums.UserRole;
-import com.platform2easy.genesis.domain.model.User;
+import com.platform2easy.genesis.domain.model.User2Easy;
 import com.platform2easy.genesis.domain.repository.UserRepository;
 import org.springframework.boot.CommandLineRunner;
 import org.springframework.boot.SpringApplication;
@@ -19,7 +19,9 @@ public class GenesisApplication {
     @Bean
     public CommandLineRunner initDataBase(UserRepository user) {
         return args -> {
-            user.save(new User(null, "admin", new BCryptPasswordEncoder().encode("admin"), UserRole.ADMIN));
+            user.save(new User2Easy(null, "admin", new BCryptPasswordEncoder().encode("admin"), "Administrador", UserRole.ADMIN));
+            user.save(new User2Easy(null, "compra", new BCryptPasswordEncoder().encode("compra"), "Comprador", UserRole.BUYER_USER));
+            user.save(new User2Easy(null, "venda", new BCryptPasswordEncoder().encode("venda"), "Vendedor", UserRole.SELLER_USER));
         };
     }
 }

+ 3 - 2
src/main/java/com/platform2easy/genesis/domain/model/User.java → src/main/java/com/platform2easy/genesis/domain/model/User2Easy.java

@@ -26,8 +26,8 @@ import java.util.Collections;
 @AllArgsConstructor
 @NoArgsConstructor
 @EqualsAndHashCode(onlyExplicitlyIncluded = true)
-@Table(name = "PLATFORM_USER")
-public class User implements UserDetails {
+@Table(name = "USER_2EASY")
+public class User2Easy implements UserDetails {
 
     @Id
     @GeneratedValue(strategy = GenerationType.IDENTITY)
@@ -36,6 +36,7 @@ public class User implements UserDetails {
 
     private String login;
     private String password;
+    private String nome;
 
     @Enumerated(EnumType.STRING)
     private UserRole role;

+ 2 - 2
src/main/java/com/platform2easy/genesis/domain/repository/UserRepository.java

@@ -1,9 +1,9 @@
 package com.platform2easy.genesis.domain.repository;
 
-import com.platform2easy.genesis.domain.model.User;
+import com.platform2easy.genesis.domain.model.User2Easy;
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.security.core.userdetails.UserDetails;
 
-public interface UserRepository extends JpaRepository<User,Long> {
+public interface UserRepository extends JpaRepository<User2Easy,Long> {
     UserDetails findByLogin(String login);
 }

+ 7 - 0
src/main/java/com/platform2easy/genesis/domain/service/UserService.java

@@ -1,5 +1,6 @@
 package com.platform2easy.genesis.domain.service;
 
+import com.platform2easy.genesis.domain.model.User2Easy;
 import com.platform2easy.genesis.domain.repository.UserRepository;
 import lombok.AllArgsConstructor;
 import org.springframework.security.core.userdetails.UserDetails;
@@ -7,6 +8,8 @@ import org.springframework.security.core.userdetails.UserDetailsService;
 import org.springframework.security.core.userdetails.UsernameNotFoundException;
 import org.springframework.stereotype.Service;
 
+import java.util.List;
+
 @Service
 @AllArgsConstructor
 public class UserService implements UserDetailsService {
@@ -17,4 +20,8 @@ public class UserService implements UserDetailsService {
     public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
         return userRepository.findByLogin(username);
     }
+
+    public List<User2Easy> listAll(){
+        return userRepository.findAll();
+    }
 }

+ 2 - 2
src/main/java/com/platform2easy/genesis/security/service/TokenService.java

@@ -4,7 +4,7 @@ import com.auth0.jwt.JWT;
 import com.auth0.jwt.algorithms.Algorithm;
 import com.auth0.jwt.exceptions.JWTCreationException;
 import com.auth0.jwt.exceptions.JWTVerificationException;
-import com.platform2easy.genesis.domain.model.User;
+import com.platform2easy.genesis.domain.model.User2Easy;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 
@@ -18,7 +18,7 @@ public class TokenService {
     @Value("${api.security.token.secret}")
     private String secret;
 
-    public String generateToken(User user) {
+    public String generateToken(User2Easy user) {
         try {
             var algorithm = Algorithm.HMAC256(secret);
             return JWT.create()

+ 2 - 2
src/main/java/com/platform2easy/genesis/web/api/AuthenticationController.java

@@ -1,6 +1,6 @@
 package com.platform2easy.genesis.web.api;
 
-import com.platform2easy.genesis.domain.model.User;
+import com.platform2easy.genesis.domain.model.User2Easy;
 import com.platform2easy.genesis.security.service.TokenService;
 import com.platform2easy.genesis.web.dto.authentication.AuthenticationDTO;
 import com.platform2easy.genesis.web.dto.authentication.LoginResponseDTO;
@@ -26,7 +26,7 @@ public class AuthenticationController {
     public ResponseEntity login(@RequestBody @Valid AuthenticationDTO data) {
         var usernamePassword = new UsernamePasswordAuthenticationToken(data.login(), data.password());
         var auth = this.authenticationManager.authenticate(usernamePassword);
-        var token = tokenService.generateToken((User) auth.getPrincipal());
+        var token = tokenService.generateToken((User2Easy) auth.getPrincipal());
         return ResponseEntity.ok(new LoginResponseDTO(token));
     }
 

+ 23 - 0
src/main/java/com/platform2easy/genesis/web/controller/UserController.java

@@ -0,0 +1,23 @@
+package com.platform2easy.genesis.web.controller;
+
+import com.platform2easy.genesis.domain.service.UserService;
+import lombok.AllArgsConstructor;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+@Controller
+@RequestMapping("user")
+@AllArgsConstructor
+public class UserController {
+
+    private final UserService userService;
+
+    @GetMapping("listar")
+    public String listar(Model model) {
+        model.addAttribute("titulo", "Usuários");
+        model.addAttribute("users", userService.listAll());
+        return "users/list";
+    }
+}

+ 5 - 2
src/main/resources/application.properties

@@ -2,6 +2,11 @@ spring.application.name=genesis
 
 server.port=8080
 
+server.error.whitelabel.enabled=false
+server.error.include-message=never
+
+api.security.token.secret=${JWT_SECRET:my-secret-key}
+
 #datasource
 spring.datasource.url=jdbc:h2:mem:banco
 spring.datasource.username=sa
@@ -15,5 +20,3 @@ spring.jpa.hibernate.ddl-auto=update
 #h2
 spring.h2.console.enabled=true
 spring.h2.console.path=/banco
-
-api.security.token.secret=${JWT_SECRET:my-secret-key}

+ 0 - 2
src/main/resources/static/css/estilo.css

@@ -39,7 +39,5 @@ body {
 footer {
   height: 50px;
   line-height: 50px;
-  background-color: #212529;
-  color: white;
   text-align: center;
 }

+ 1 - 1
src/main/resources/templates/Index.html

@@ -8,7 +8,7 @@
 </head>
 <body>
 <section layout:fragment="main-content">
-    <div class="container">
+    <div class="container p-4 shadow bg-white rounded">
         <h1 class="mb-4" th:text="${titulo}"></h1>
         <div class="row">
             <div class="col-md-4 mb-4">

+ 1 - 1
src/main/resources/templates/compra/formulario.html

@@ -8,7 +8,7 @@
 </head>
 <body>
 <section layout:fragment="main-content">
-    <div class="container">
+    <div class="container p-4 shadow bg-white rounded">
         <h1 class="mb-4" th:text="${titulo}"></h1>
         <form>
             <div class="mb-3">

+ 1 - 1
src/main/resources/templates/compra/lista.html

@@ -8,7 +8,7 @@
 </head>
 <body>
 <section layout:fragment="main-content">
-    <div class="container">
+    <div class="container p-4 shadow bg-white rounded">
         <h1 class="mb-4" th:text="${titulo}"></h1>
         <table class="table table-hover">
             <thead>

+ 16 - 0
src/main/resources/templates/error/404.html

@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html xmlns:th="http://www.thymeleaf.org">
+<head th:insert="~{layout :: head}">
+    <meta charset="UTF-8">
+</head>
+<body class="d-flex flex-column min-vh-100">
+<nav th:insert="~{login :: top}"></nav>
+<main class="container text-center my-auto">
+    <h1 class="display-4">404</h1>
+    <p class="lead">A página que você está procurando não foi encontrada.</p>
+    <a th:href="@{/}" class="btn btn-dark">Voltar para o início</a>
+</main>
+<footer th:insert="~{layout :: footer}"></footer>
+<div th:insert="~{layout :: script}"></div>
+</body>
+</html>

+ 11 - 10
src/main/resources/templates/layout.html

@@ -2,7 +2,7 @@
 <html lang="en"
       xmlns:th="http://www.thymeleaf.org"
       xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
-<head>
+<head th:fragment="head">
     <meta charset="UTF-8">
     <title>Too Easy</title>
     <meta name="viewport" content="width=device-width, initial-scale=1">
@@ -28,7 +28,7 @@
     <div class="row h-100">
         <nav class="col-md-2 bg-dark sidebar collapse d-md-block" id="mobileMenu">
             <a th:href="@{/}">🏠 Início</a>
-            <a href="#">👥 Usuários</a>
+            <a th:href="@{/user/listar}">👥 Usuários</a>
 
             <a class="dropdown-toggle d-block text-white" data-bs-toggle="collapse" href="#compras-submenu"
                role="button" aria-expanded="false" aria-controls="compras-submenu">
@@ -56,18 +56,19 @@
     </div>
 </div>
 
-<footer class="bg-dark text-white text-center">
+<footer th:fragment="footer" class="bg-dark text-white text-center">
     <div class="container">
         <small>&copy; 2025 TooEasy. Todos os direitos reservados.</small>
     </div>
 </footer>
 
-<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.8/dist/umd/popper.min.js"
-        integrity="sha384-I7E8VVD/ismYTF4hNIPjVp/Zjvgyol6VFvRkX/vR+Vc4jQkC+hVqc2pM8ODewa9r"
-        crossorigin="anonymous"></script>
-<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.6/dist/js/bootstrap.min.js"
-        integrity="sha384-RuyvpeZCxMJCqVUGFI0Do1mQrods/hhxYlcVfGPOfQtPJh0JCw12tUAZ/Mv10S7D"
-        crossorigin="anonymous"></script>
-
+<div th:fragment="script">
+    <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.8/dist/umd/popper.min.js"
+            integrity="sha384-I7E8VVD/ismYTF4hNIPjVp/Zjvgyol6VFvRkX/vR+Vc4jQkC+hVqc2pM8ODewa9r"
+            crossorigin="anonymous"></script>
+    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.6/dist/js/bootstrap.min.js"
+            integrity="sha384-RuyvpeZCxMJCqVUGFI0Do1mQrods/hhxYlcVfGPOfQtPJh0JCw12tUAZ/Mv10S7D"
+            crossorigin="anonymous"></script>
+</div>
 </body>
 </html>

+ 14 - 4
src/main/resources/templates/login.html

@@ -1,13 +1,20 @@
 <!DOCTYPE html>
 <html lang="pt-br" xmlns:th="http://www.thymeleaf.org">
-<head>
+<head th:insert="~{layout :: head}">
     <meta charset="UTF-8">
-    <title>Login</title>
-    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
 </head>
 <body class="bg-light">
+
+<div th:fragment="top" class="navbar navbar-expand-md navbar-dark bg-dark sticky-top">
+    <div class="container-fluid">
+        <div class="navbar-brand">
+            <img th:src="@{/images/too-easy-trade.png}" class="img-fluid" style="max-width: 100px;">
+        </div>
+    </div>
+</div>
+
 <div class="container d-flex justify-content-center align-items-center" style="height: 100vh;">
-    <form class="p-4 shadow bg-white rounded" method="post" th:action="@{/login}">
+    <form class="p-5 shadow bg-white rounded w-100" style="max-width: 500px;" method="post" th:action="@{/login}">
         <h4 class="mb-4">Login Admin</h4>
         <div class="mb-3">
             <input class="form-control" type="text" name="username" placeholder="Usuário">
@@ -20,5 +27,8 @@
         </div>
     </form>
 </div>
+
+<footer th:insert="~{layout :: footer}"></footer>
+<div th:insert="~{layout :: script}"></div>
 </body>
 </html>

+ 73 - 0
src/main/resources/templates/users/form.html

@@ -0,0 +1,73 @@
+<!DOCTYPE html>
+<html lang="en" xmlns:th="http://www.thymeleaf.org"
+      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
+      layout:decorate="~{layout}">
+<head>
+    <meta charset="UTF-8">
+    <title>Too Easy</title>
+</head>
+<body>
+<section layout:fragment="main-content">
+    <div class="container p-4 shadow bg-white rounded">
+        <h1 class="mb-4" th:text="${titulo}"></h1>
+        <form>
+            <div class="mb-3">
+                <input hidden="true" name="id" th:value="${compra.id}" type="text">
+
+                <label class="form-label" for="fornecedor">Fornecedor</label>
+                <input class="form-control" id="fornecedor" name="fornecedor" th:value="${compra.fornecedor}"
+                       type="text">
+            </div>
+
+            <br/>
+            <div class="mb-3">
+                <table class="table">
+                    <thead>
+                    <tr>
+                        <th>Código</th>
+                        <th>Item</th>
+                        <th>Valor</th>
+                        <th></th>
+                    </tr>
+                    </thead>
+                    <tbody>
+                    <tr th:each="item, stat : ${compra.itens}">
+                        <td>
+                            <input th:value="${item.id}" th:name="|itens[${stat.index}].id|" type="text" hidden="true">
+                            <input th:value="${item.id}" class="form-control" type="text" disabled>
+                        </td>
+                        <td>
+                            <input th:value="${item.descricao}" class="form-control"
+                                   th:name="|itens[${stat.index}].descricao|" type="text" required>
+                        </td>
+                        <td><input th:value="${item.valor}" class="form-control" th:name="|itens[${stat.index}].valor|"
+                                   type="text" required></td>
+                        <td>
+                            <button class="btn btn-outline-dark" formmethod="post"
+                                    th:formaction="@{'/compra/' + ${stat.index}}"
+                                    type="submit">
+                                <i class="bi bi-dash-square"></i>
+                            </button>
+                        </td>
+                    </tr>
+                    <tr>
+                        <td><input class="form-control" type="text" disabled></td>
+                        <td><input class="form-control" th:name="descricao" type="text"></td>
+                        <td><input class="form-control" th:name="valor" type="text"></td>
+                        <td>
+                            <button class="btn btn-outline-dark" formmethod="post" th:formaction="@{/compra}"
+                                    type="submit">
+                                <i class="bi bi-plus-square"></i>
+                            </button>
+                    </tr>
+                    </tbody>
+                </table>
+            </div>
+
+            <button class="btn btn-dark" formmethod="post" th:formaction="@{/compra/salvar}" type="submit">Salvar
+            </button>
+        </form>
+    </div>
+</section>
+</body>
+</html>

+ 43 - 0
src/main/resources/templates/users/list.html

@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html lang="en" xmlns:th="http://www.thymeleaf.org"
+      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
+      layout:decorate="~{layout}">
+<head>
+    <meta charset="UTF-8">
+    <title>Too Easy</title>
+</head>
+<body>
+<section layout:fragment="main-content">
+    <div class="container p-4 shadow bg-white rounded">
+        <h1 class="mb-4" th:text="${titulo}"></h1>
+        <table class="table table-hover">
+            <thead>
+            <tr>
+                <th>Código</th>
+                <th>Nome</th>
+                <th>Previlégio</th>
+                <th>Ações</th>
+            </tr>
+            </thead>
+            <tbody>
+            <tr th:each="user : ${users}">
+                <td th:text="${user.id}"></td>
+                <td th:text="${user.nome}"></td>
+                <td th:text="${user.role}"></td>
+                <td>
+                    <a th:href="@{'/user/editar/' + ${user.id}}" type="button" class="btn btn-outline-dark"
+                       title="Editar">
+                        <i class="bi bi-pencil-square"></i>
+                    </a>
+                    <a th:href="@{'/user/remover/' + ${user.id}}" type="button" class="btn btn-outline-dark"
+                       title="Remover">
+                        <i class="bi bi-dash-square"></i>
+                    </a>
+                </td>
+            </tr>
+            </tbody>
+        </table>
+    </div>
+</section>
+</body>
+</html>