From d02328857480bbbba16b7c369a02cbcb0e20ede6 Mon Sep 17 00:00:00 2001 From: freddyheredia4 Date: Mon, 5 Jun 2023 19:42:47 -0500 Subject: [PATCH] =?UTF-8?q?clase=20de=20autenticacion,=20autorizaci=C3=B3n?= =?UTF-8?q?,=20documentacion=20y=20relaciones=20one=20to=20many?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 7 + .../authz/conf/JWTAuthenticationFilter.java | 127 ++++++++++++++++++ .../authz/conf/JWTAuthorizationFilter.java | 63 +++++++++ .../pedidos/core/authz/conf/JWTUtil.java | 55 ++++++++ .../authz/conf/SecurityConfiguration.java | 39 ++++++ .../authz/controller/AuthorityController.java | 72 ++++++++++ .../core/authz/controller/RoleController.java | 64 +++++++++ .../core/authz/controller/UserController.java | 109 +++++++++++++++ .../pedidos/core/authz/entity/Authority.java | 21 +++ .../pedidos/core/authz/entity/Role.java | 37 +++++ .../pedidos/core/authz/entity/User.java | 79 +++++++++++ .../authz/repository/AuthorityRepository.java | 30 +++++ .../core/authz/repository/RoleRepository.java | 15 +++ .../core/authz/repository/UserRepository.java | 29 ++++ .../core/authz/service/AuthorityService.java | 40 ++++++ .../core/authz/service/RoleService.java | 51 +++++++ .../core/authz/service/UserService.java | 107 +++++++++++++++ .../core/cliente/ClienteController.java | 9 ++ .../pedidos/core/pedidos/DetallePedido.java | 24 ++++ .../pedidos/pedidos/core/pedidos/Pedido.java | 31 +++++ .../core/pedidos/PedidoController.java | 76 +++++++++++ .../core/pedidos/PedidoRepository.java | 10 ++ .../pedidos/core/pedidos/PedidoService.java | 28 ++++ .../resources/application-prod.properties | 6 + src/main/resources/application.properties | 3 +- src/main/resources/data.sql | 54 ++++++++ 26 files changed, 1185 insertions(+), 1 deletion(-) create mode 100644 src/main/java/pedidos/pedidos/core/authz/conf/JWTAuthenticationFilter.java create mode 100644 src/main/java/pedidos/pedidos/core/authz/conf/JWTAuthorizationFilter.java create mode 100644 src/main/java/pedidos/pedidos/core/authz/conf/JWTUtil.java create mode 100644 src/main/java/pedidos/pedidos/core/authz/conf/SecurityConfiguration.java create mode 100644 src/main/java/pedidos/pedidos/core/authz/controller/AuthorityController.java create mode 100644 src/main/java/pedidos/pedidos/core/authz/controller/RoleController.java create mode 100644 src/main/java/pedidos/pedidos/core/authz/controller/UserController.java create mode 100644 src/main/java/pedidos/pedidos/core/authz/entity/Authority.java create mode 100644 src/main/java/pedidos/pedidos/core/authz/entity/Role.java create mode 100644 src/main/java/pedidos/pedidos/core/authz/entity/User.java create mode 100644 src/main/java/pedidos/pedidos/core/authz/repository/AuthorityRepository.java create mode 100644 src/main/java/pedidos/pedidos/core/authz/repository/RoleRepository.java create mode 100644 src/main/java/pedidos/pedidos/core/authz/repository/UserRepository.java create mode 100644 src/main/java/pedidos/pedidos/core/authz/service/AuthorityService.java create mode 100644 src/main/java/pedidos/pedidos/core/authz/service/RoleService.java create mode 100644 src/main/java/pedidos/pedidos/core/authz/service/UserService.java create mode 100644 src/main/java/pedidos/pedidos/core/pedidos/DetallePedido.java create mode 100644 src/main/java/pedidos/pedidos/core/pedidos/Pedido.java create mode 100644 src/main/java/pedidos/pedidos/core/pedidos/PedidoController.java create mode 100644 src/main/java/pedidos/pedidos/core/pedidos/PedidoRepository.java create mode 100644 src/main/java/pedidos/pedidos/core/pedidos/PedidoService.java create mode 100644 src/main/resources/application-prod.properties create mode 100644 src/main/resources/data.sql diff --git a/build.gradle b/build.gradle index 4c3c7b2..ae83032 100644 --- a/build.gradle +++ b/build.gradle @@ -26,6 +26,13 @@ dependencies { runtimeOnly 'org.postgresql:postgresql' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' + implementation 'org.springframework.boot:spring-boot-starter-security' + implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.0.2' + implementation 'org.springdoc:springdoc-openapi-starter-common:2.0.2' + implementation 'org.hibernate.validator:hibernate-validator:8.0.0.Final' + implementation 'io.jsonwebtoken:jjwt:0.9.1' + implementation 'javax.xml.bind:jaxb-api:2.3.1' + } tasks.named('test') { diff --git a/src/main/java/pedidos/pedidos/core/authz/conf/JWTAuthenticationFilter.java b/src/main/java/pedidos/pedidos/core/authz/conf/JWTAuthenticationFilter.java new file mode 100644 index 0000000..a4b6d76 --- /dev/null +++ b/src/main/java/pedidos/pedidos/core/authz/conf/JWTAuthenticationFilter.java @@ -0,0 +1,127 @@ +package pedidos.pedidos.core.authz.conf; + +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; + +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.transaction.Transactional; +import pedidos.pedidos.core.authz.entity.User; + +import org.springframework.security.web.authentication.AuthenticationFailureHandler; +import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.GrantedAuthority; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Base64; +import java.util.Collection; +import java.util.Date; + +import pedidos.pedidos.core.authz.service.UserService; + +public class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilter{ + private AuthenticationManager authenticationManager; + + private UserService userService; + + public JWTAuthenticationFilter(UserService userService) { + setAuthenticationFailureHandler(new JWTAuthenticationFailureHandler()); + this.userService = userService; + + } + + @Override + public Authentication attemptAuthentication(HttpServletRequest req, + HttpServletResponse res) throws AuthenticationException { + + + if (req.getHeader("Authorization")==null || req.getHeader("Authorization").isEmpty()) + throw new AuthenticationCredentialsNotFoundException("Credentials not found"); + String header=req.getHeader("Authorization").replace("Basic ",""); + + byte[] decodedBytes = Base64.getDecoder().decode(header); + header = new String(decodedBytes); + + String[] credenciales = header.split(":"); + if (credenciales.length <= 1) + throw new AuthenticationCredentialsNotFoundException("Credentials not found"); + + UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(credenciales[0], credenciales[1], new ArrayList<>()); + + Authentication auth = authenticate(authToken); + return auth; + } + + @Transactional + public Authentication authenticate(Authentication authentication) throws AuthenticationException { + String username = authentication.getName(); + String password = authentication.getCredentials().toString(); + + User user = userService.findByUsername(username); + + if (user==null) { + throw new BadCredentialsException("Usuario o contraseña inválidos"); + } + + if (!userService.matchPassword(password,user.getPassword())){ + throw new BadCredentialsException("Usuario o contraseña inválidos"); + } + user = userService.getUserWithRolesByUsername(username); + + return new UsernamePasswordAuthenticationToken(username, "", user.getAuthorities()); + } + + @Override + protected void successfulAuthentication(HttpServletRequest req, + HttpServletResponse res, + FilterChain chain, + Authentication auth) throws IOException, ServletException{ + + String username = auth.getPrincipal().toString(); + Collection authorities=auth.getAuthorities(); + String role = authorities + .stream() + .map(authName -> authName.getAuthority()+";") + .reduce("", String::concat); + role = role.substring(0, role.length()-1); + String token = JWTUtil.generateToken(username, role); + res.addHeader("Authorization", "Bearer " + token); + res.addHeader("Access-Control-Expose-Headers", "Authorization"); + } + + @Override + public AuthenticationManager getAuthenticationManager(){ + return this.authenticationManager; + } + + private class JWTAuthenticationFailureHandler implements AuthenticationFailureHandler { + + @Override + public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) + throws IOException, ServletException { + response.setStatus(401); + response.setContentType("application/json"); + response.getWriter().append(json(exception.getLocalizedMessage())); + + } + + private String json(String message) { + long date = new Date().getTime(); + return "{\"timestamp\": " + date + ", " + + "\"status\": 401, " + + "\"error\": \"Not authorized\", " + + "\"message\": "+ message+ ", " + + "\"path\": \"/login\"}"; + } + } + + +} + diff --git a/src/main/java/pedidos/pedidos/core/authz/conf/JWTAuthorizationFilter.java b/src/main/java/pedidos/pedidos/core/authz/conf/JWTAuthorizationFilter.java new file mode 100644 index 0000000..421b0db --- /dev/null +++ b/src/main/java/pedidos/pedidos/core/authz/conf/JWTAuthorizationFilter.java @@ -0,0 +1,63 @@ +package pedidos.pedidos.core.authz.conf; + +import java.io.IOException; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.context.SecurityContextHolder; +import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpFilter; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import pedidos.pedidos.core.authz.entity.User; +import pedidos.pedidos.core.authz.service.UserService; + + +public class JWTAuthorizationFilter extends HttpFilter { + + UserService userService; + + public JWTAuthorizationFilter(UserService userService) { + this.userService = userService; + } + @Override + protected void doFilter(HttpServletRequest request, + HttpServletResponse response, FilterChain chain) + throws IOException, ServletException { + String header=request.getHeader(JWTUtil.TOKEN_HEADER); + System.out.println(request.getMethod()); + if(header==null||!header.startsWith(JWTUtil.TOKEN_PREFIX)){ + chain.doFilter(request,response); + return; + } + UsernamePasswordAuthenticationToken authentication = null; + try { + authentication = getAuthentication(header); + }catch (RuntimeException ex ) { + response.setCharacterEncoding("UTF-8"); + response.setContentType("application/json; charset=utf-8"); + response.setStatus(HttpServletResponse.SC_FORBIDDEN); + response.getWriter().write(new ObjectMapper().writeValueAsString("No access, "+ex.getMessage())); + return; + } + SecurityContextHolder.getContext().setAuthentication(authentication); + chain.doFilter(request, response); + } + + private UsernamePasswordAuthenticationToken getAuthentication(String header) { + String token = header.replace(JWTUtil.TOKEN_PREFIX, ""); + + String username = JWTUtil.getUsername(token); + + if (JWTUtil.isExpiered(token)) + return null; + + User usuario = userService.getUserWithAuthoritiesByUsername(username); + + if (username != null) { + return new UsernamePasswordAuthenticationToken(username, null,usuario.getAuthorities() + ); + } + return null; + } +} diff --git a/src/main/java/pedidos/pedidos/core/authz/conf/JWTUtil.java b/src/main/java/pedidos/pedidos/core/authz/conf/JWTUtil.java new file mode 100644 index 0000000..a115cff --- /dev/null +++ b/src/main/java/pedidos/pedidos/core/authz/conf/JWTUtil.java @@ -0,0 +1,55 @@ +package pedidos.pedidos.core.authz.conf; + +import java.sql.Date; +import java.util.HashMap; +import java.util.Map; + +import org.springframework.stereotype.Component; + +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import io.jsonwebtoken.SignatureException; + +@Component +public class JWTUtil { + + + public static final String TOKEN_HEADER="Authorization"; + public static final String TOKEN_PREFIX="Bearer "; + private static final String SECRET="$2a$12$r8pfiCwWEGH0lavcBqcmJOYqEm.VoaUqq6VtuzKFEgaVTRFNVo1ea"; + private static final long EXPIRATION=12000; + private static final String ROLE_CLAIMS="rol"; + + + public static String generateToken(String username, String role) { + Map map=new HashMap<>(); + map.put(ROLE_CLAIMS,role); + return Jwts.builder() + .signWith(SignatureAlgorithm.HS512,SECRET) + .setClaims(map) + .setSubject(username) + .setExpiration(new Date(System.currentTimeMillis()+EXPIRATION*1000)) + .compact(); + } + + public static String getUsername(String token) throws SignatureException{ + return getTokenBody(token).getSubject(); + } + public static String getUserRole(String token){ + return (String) getTokenBody(token).get(ROLE_CLAIMS); + } + + private static Claims getTokenBody(String token) throws SignatureException{ + + return Jwts.parser() + .setSigningKey(SECRET) + .parseClaimsJws(token) + .getBody(); + } + + public static boolean isExpiered(String token) throws SignatureException{ + + return getTokenBody(token).getExpiration().before(new Date(System.currentTimeMillis())); + } +} diff --git a/src/main/java/pedidos/pedidos/core/authz/conf/SecurityConfiguration.java b/src/main/java/pedidos/pedidos/core/authz/conf/SecurityConfiguration.java new file mode 100644 index 0000000..6f62359 --- /dev/null +++ b/src/main/java/pedidos/pedidos/core/authz/conf/SecurityConfiguration.java @@ -0,0 +1,39 @@ +package pedidos.pedidos.core.authz.conf; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; +import pedidos.pedidos.core.authz.service.UserService; + +@Configuration +@EnableWebSecurity +@EnableMethodSecurity(prePostEnabled = true) +public class SecurityConfiguration{ + + @Autowired + private UserService userService; + + @Bean + public SecurityFilterChain apiFilterChain(HttpSecurity http) throws Exception { + + http + .csrf().disable() + .authorizeHttpRequests((authorize) -> authorize + .requestMatchers("/login").permitAll() + .requestMatchers("/swagger-ui/*").permitAll() + .requestMatchers("/v3/api-docs").permitAll() + .requestMatchers("/v3/api-docs/*").permitAll() + .requestMatchers("/v3/*").permitAll() + .anyRequest().authenticated() + ); + http.addFilterBefore(new JWTAuthenticationFilter(userService), BasicAuthenticationFilter.class); + http.addFilterAfter(new JWTAuthorizationFilter(userService),BasicAuthenticationFilter.class); + return http.build(); + + } +} diff --git a/src/main/java/pedidos/pedidos/core/authz/controller/AuthorityController.java b/src/main/java/pedidos/pedidos/core/authz/controller/AuthorityController.java new file mode 100644 index 0000000..f1e62b9 --- /dev/null +++ b/src/main/java/pedidos/pedidos/core/authz/controller/AuthorityController.java @@ -0,0 +1,72 @@ +package pedidos.pedidos.core.authz.controller; + +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import pedidos.pedidos.core.authz.entity.Authority; +import pedidos.pedidos.core.authz.service.AuthorityService; + + +@RestController +@CrossOrigin({"*"}) +@RequestMapping("/api/authority") +@Tag(name = "Controlador Authority (Permisos)", description = "Tabla authorities") +public class AuthorityController { + + @Autowired + AuthorityService authorityService; + + @Operation(summary = "Obtiene un permiso por su id, Requiere Authority_Read") + @PreAuthorize("hasAuthority('Authority_Read')") + @GetMapping("/{id}/") + public Authority findById(@PathVariable long id){ + return authorityService.findById(id); + } + + @Operation(summary = "Obtiene un listado de todos los permisos, Requiere Authority_Read") + @PreAuthorize("hasAuthority('Authority_Read')") + @GetMapping("/") + public List findAll(){ + return authorityService.findAll(); + } + + @Operation(summary = "Guarda un permiso (enviado por el body), Requiere Authority_Write") + //@PreAuthorize("hasAuthority('Authority_Write')") + @PostMapping("/") + public Authority save(@RequestBody Authority authority){ + return authorityService.save(authority); + } + + @Operation(summary = "Actualiza un permiso (enviado por el body), Requiere Authority_Write") + @PreAuthorize("hasAuthority('Authority_Write')") + @PutMapping("/{id}/") + public Authority update(@RequestBody Authority authority){ + return authorityService.save(authority); + } + + @Operation(summary = "Borra un permiso (enviado por el body), Requiere Authority_Delete") + @PreAuthorize("hasAuthority('Authority_Delete')") + @DeleteMapping("/{id}/") + public void deleteById(@PathVariable long id){ + authorityService.deleteById(id); + } + + @Operation(summary = "Obtiene una lista de permisos de un usuario, Requiere AuthorityByUser_Read") + @PreAuthorize("hasAuthority('AuthorityByUser_Read')") + @GetMapping("/byuser/{username}/") + public List findByUsename(@PathVariable String username){ + return authorityService.findByUsername(username); + } +} diff --git a/src/main/java/pedidos/pedidos/core/authz/controller/RoleController.java b/src/main/java/pedidos/pedidos/core/authz/controller/RoleController.java new file mode 100644 index 0000000..d3a37f2 --- /dev/null +++ b/src/main/java/pedidos/pedidos/core/authz/controller/RoleController.java @@ -0,0 +1,64 @@ +package pedidos.pedidos.core.authz.controller; + +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import pedidos.pedidos.core.authz.entity.Role; +import pedidos.pedidos.core.authz.service.RoleService; + +@Tag(name = "Controlador Role (Roles)", description = "Tabla roles") +@RestController +@CrossOrigin({"*"}) +@RequestMapping("/api/role") +public class RoleController { + + @Autowired + RoleService roleService; + + @Operation(summary = "Obtiene un rol por su id, Requiere Role_Read") + @PreAuthorize("hasAuthority('Role_Read')") + @GetMapping("/{id}/") + public Role findById(@PathVariable long id){ + return roleService.findById(id); + } + + @Operation(summary = "Obtiene un listado de todos los roles, Requiere Role_Read") + @PreAuthorize("hasAuthority('Role_Read')") + @GetMapping("/") + public List findAll(){ + return roleService.findAll(); + } + + @Operation(summary = "Guarda un nuevo rol (enviado en el body), Requiere Role_Write") + @PreAuthorize("hasAuthority('Role_Write')") + @PostMapping("/") + public Role save(@RequestBody Role role){ + return roleService.save(role); + } + + @Operation(summary = "Actualiza un rol por su id, Requiere Role_Write") + @PreAuthorize("hasAuthority('Role_Write')") + @PutMapping("/{id}/") + public Role update(@RequestBody Role role){ + return roleService.save(role); + } + + @Operation(summary = "Borra un rol por su id, Requiere Role_Delete") + @PreAuthorize("hasAuthority('Role_Delete')") + @DeleteMapping("/{id}/") + public void deleteById(@PathVariable long id){ + roleService.deleteById(id); + } +} diff --git a/src/main/java/pedidos/pedidos/core/authz/controller/UserController.java b/src/main/java/pedidos/pedidos/core/authz/controller/UserController.java new file mode 100644 index 0000000..b8c7877 --- /dev/null +++ b/src/main/java/pedidos/pedidos/core/authz/controller/UserController.java @@ -0,0 +1,109 @@ +package pedidos.pedidos.core.authz.controller; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import pedidos.pedidos.core.authz.conf.JWTUtil; +import pedidos.pedidos.core.authz.entity.Authority; +import pedidos.pedidos.core.authz.entity.User; +import pedidos.pedidos.core.authz.service.AuthorityService; +import pedidos.pedidos.core.authz.service.UserService; + +@Tag(name = "Controlador User (Usuarios)", description = "Tabla users") +@RestController +@CrossOrigin({"*"}) +@RequestMapping("/api/user") +public class UserController { + + @Autowired + UserService userService; + @Autowired + AuthorityService authorityService; + + @Operation(summary = "Obtiene un usuario por su id, Requiere User_Read") + @PreAuthorize("hasAuthority('User_Read')") + @GetMapping("/{id}/") + public User findById(@PathVariable long id){ + return userService.findById(id); + } + + @Operation(summary = "Obtiene un listado de usuario, Requiere User_Read") + @PreAuthorize("hasAuthority('User_Read')") + @GetMapping("/") + public List findAll(){ + return userService.findAll(); + } + + @Operation(summary = "Guarda un usuario (body), Requiere User_Write") + @PreAuthorize("hasAuthority('User_Write')") + @PostMapping("/") + public User save(@RequestBody User user){ + return userService.save(user); + } + + @Operation(summary = "Actualización de todos los valores de un usuario (body) a través de su ID, Requiere User_Write") + @PreAuthorize("hasAuthority('User_Write')") + @PutMapping("/{id}/") + public User update(@RequestBody User user){ + return userService.save(user); + } + + @Operation(summary = "Borra un usuario a través de su ID, Requiere User_Delete") + @PreAuthorize("hasAuthority('User_Delete')") + @DeleteMapping("/{id}/") + public void deleteById(@PathVariable long id){ + userService.deleteById(id); + } + + + @Operation(summary = "Entrega un Ok en caso de que el usuario extraido del token tiene acceso al Endpoint solicitado (Header), en caso contrario se entrega un 403") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", + description = "OK", + content = {@Content(mediaType = "application/json")}), + @ApiResponse(responseCode = "403", + description = "FORBIDDEN", + content = @Content) + }) + @GetMapping("/hasAuthority/") + public ResponseEntity hasAuthority(@RequestHeader("Authorization") String authHeader, @RequestHeader("Endpoint") String endpointHeader){ + + if(authHeader==null||!authHeader.startsWith("Bearer")){ + return ResponseEntity.status(HttpStatus.FORBIDDEN).build(); + } + + String token = authHeader.replace("Bearer ", ""); + String username = JWTUtil.getUsername(token); + + if (username==null || endpointHeader == null ) + return ResponseEntity.status(HttpStatus.FORBIDDEN).build(); + List authorities = authorityService.findByUsername(username); + + for (Authority auth: authorities){ + if (endpointHeader.equals(auth.getEndpoint())){ + return ResponseEntity.ok("ok"); + } + } + + return ResponseEntity.status(HttpStatus.FORBIDDEN).body("No access"); + } +} + diff --git a/src/main/java/pedidos/pedidos/core/authz/entity/Authority.java b/src/main/java/pedidos/pedidos/core/authz/entity/Authority.java new file mode 100644 index 0000000..604f1bd --- /dev/null +++ b/src/main/java/pedidos/pedidos/core/authz/entity/Authority.java @@ -0,0 +1,21 @@ +package pedidos.pedidos.core.authz.entity; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import lombok.Data; + +@Data +@Entity +@Table(name="authorities") +public class Authority { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private long id; + private String name; + private String endpoint; + +} diff --git a/src/main/java/pedidos/pedidos/core/authz/entity/Role.java b/src/main/java/pedidos/pedidos/core/authz/entity/Role.java new file mode 100644 index 0000000..2c0f763 --- /dev/null +++ b/src/main/java/pedidos/pedidos/core/authz/entity/Role.java @@ -0,0 +1,37 @@ +package pedidos.pedidos.core.authz.entity; +import java.util.List; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinTable; +import jakarta.persistence.ManyToMany; +import jakarta.persistence.Table; +import jakarta.persistence.JoinColumn; + +import lombok.Data; + +@Data +@Entity +@Table(name="roles") +public class Role { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private long id; + + private String name; + + @Column(columnDefinition = "boolean default true") + private boolean enabled; + + @ManyToMany + @JoinTable(name = "roles_authorities", + joinColumns = @JoinColumn(name = "role_id"), + inverseJoinColumns = @JoinColumn(name = "authority_id")) + private List authorities; + + +} diff --git a/src/main/java/pedidos/pedidos/core/authz/entity/User.java b/src/main/java/pedidos/pedidos/core/authz/entity/User.java new file mode 100644 index 0000000..553b9bd --- /dev/null +++ b/src/main/java/pedidos/pedidos/core/authz/entity/User.java @@ -0,0 +1,79 @@ +package pedidos.pedidos.core.authz.entity; +import java.util.Collection; +import java.util.List; + +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinTable; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToMany; +import jakarta.persistence.Table; +import jakarta.persistence.Transient; +import lombok.Data; + +@Data +@Entity +@Table(name="users") +public class User implements UserDetails{ + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private long id; + private String password; + private String name; + private String username; + private boolean looked = false; + private boolean expired = false; + private boolean enabled = true; + + @ManyToMany + @JoinTable(name = "users_roles", + joinColumns = @JoinColumn(name = "user_id"), + inverseJoinColumns = @JoinColumn(name = "role_id")) + private List roles; + + @Transient + private Collection authorities; + + @Override + public Collection getAuthorities() { + return this.authorities; + } + + @Override + public String getPassword() { + return this.password; + } + + @Override + public String getUsername() { + return this.username; + } + + @Override + public boolean isAccountNonExpired() { + return !this.expired; + } + + @Override + public boolean isAccountNonLocked() { + return !this.looked; + } + + @Override + public boolean isCredentialsNonExpired() { + return true; + } + + @Override + public boolean isEnabled() { + return enabled; + } + + +} \ No newline at end of file diff --git a/src/main/java/pedidos/pedidos/core/authz/repository/AuthorityRepository.java b/src/main/java/pedidos/pedidos/core/authz/repository/AuthorityRepository.java new file mode 100644 index 0000000..2b368c2 --- /dev/null +++ b/src/main/java/pedidos/pedidos/core/authz/repository/AuthorityRepository.java @@ -0,0 +1,30 @@ +package pedidos.pedidos.core.authz.repository; +import java.util.List; + +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.CrudRepository; + +import pedidos.pedidos.core.authz.entity.Authority; + + + +public interface AuthorityRepository extends CrudRepository { + + List findAll(); + + @Query( + value = + "select a.* " + + "from authorities a "+ + "join roles_authorities ra on (a.id = ra.authority_id) "+ + "join users_roles ur on (ra.role_id = ur.role_id) "+ + "join users u on (ur.user_id = u.id) "+ + "where u.username = ?1", + nativeQuery = true + ) + List findByUsername(String username); + + List findByNameIgnoreCaseLike(String term); + +} + diff --git a/src/main/java/pedidos/pedidos/core/authz/repository/RoleRepository.java b/src/main/java/pedidos/pedidos/core/authz/repository/RoleRepository.java new file mode 100644 index 0000000..719f27c --- /dev/null +++ b/src/main/java/pedidos/pedidos/core/authz/repository/RoleRepository.java @@ -0,0 +1,15 @@ +package pedidos.pedidos.core.authz.repository; +import java.util.List; + +import org.springframework.data.repository.CrudRepository; + +import pedidos.pedidos.core.authz.entity.Role; + + + + +public interface RoleRepository extends CrudRepository { + + List findAll(); + +} diff --git a/src/main/java/pedidos/pedidos/core/authz/repository/UserRepository.java b/src/main/java/pedidos/pedidos/core/authz/repository/UserRepository.java new file mode 100644 index 0000000..7bb0c16 --- /dev/null +++ b/src/main/java/pedidos/pedidos/core/authz/repository/UserRepository.java @@ -0,0 +1,29 @@ +package pedidos.pedidos.core.authz.repository; +import java.util.List; + +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.CrudRepository; + +import pedidos.pedidos.core.authz.entity.User; + + +public interface UserRepository extends CrudRepository { + + List findAll(); + + User findByUsernameAndPassword(String username, String password); + + User findByUsername(String username); + + @Query(value = + "select exists(select true as exists "+ + "from users u "+ + "join users_roles ur on (u.id = ur.user_id) "+ + "join roles r on (ur.role_id = r.id) "+ + "join roles_authorities ra on (r.id = ra.role_id) "+ + "join authorities a on (ra.authority_id = a.id) "+ + "where u.username = ?1 and a.endpoint= ?2)", + nativeQuery = true) + boolean hasAuthority(String username, String authority); + +} \ No newline at end of file diff --git a/src/main/java/pedidos/pedidos/core/authz/service/AuthorityService.java b/src/main/java/pedidos/pedidos/core/authz/service/AuthorityService.java new file mode 100644 index 0000000..ad5c7fd --- /dev/null +++ b/src/main/java/pedidos/pedidos/core/authz/service/AuthorityService.java @@ -0,0 +1,40 @@ +package pedidos.pedidos.core.authz.service; +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import pedidos.pedidos.core.authz.entity.Authority; +import pedidos.pedidos.core.authz.repository.AuthorityRepository; + + +@Service +public class AuthorityService { + + @Autowired + AuthorityRepository authorityRepository; + //Create and Update + public Authority save(Authority authority){ + return authorityRepository.save(authority); + } + //Read + public Authority findById(long id){ + return authorityRepository.findById(id).orElseThrow(); + } + //Delete + public void deleteById(long id){ + authorityRepository.deleteById(id); + } + + public List findAll(){ + return authorityRepository.findAll(); + } + + public List findByUsername(String username){ + return authorityRepository.findByUsername(username); + } + + public List findByName(String term){ + return authorityRepository.findByNameIgnoreCaseLike(term+"%"); + } +} diff --git a/src/main/java/pedidos/pedidos/core/authz/service/RoleService.java b/src/main/java/pedidos/pedidos/core/authz/service/RoleService.java new file mode 100644 index 0000000..6f8a74e --- /dev/null +++ b/src/main/java/pedidos/pedidos/core/authz/service/RoleService.java @@ -0,0 +1,51 @@ +package pedidos.pedidos.core.authz.service; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import pedidos.pedidos.core.authz.entity.Authority; +import pedidos.pedidos.core.authz.entity.Role; +import pedidos.pedidos.core.authz.repository.RoleRepository; + + +@Service +public class RoleService { + + @Autowired + RoleRepository roleRepository; + @Autowired + AuthorityService authorityService; + + //Create and Update + public Role save(Role role){ + return roleRepository.save(role); + } + //Read + public Role findById(long id){ + return roleRepository.findById(id).orElseThrow(); + } + //Delete + public void deleteById(long id){ + roleRepository.deleteById(id); + } + + public List findAll(){ + return roleRepository.findAll(); + } + + public List getAuthoritiesByRolid(long rolId) + { + List authorityNames = new ArrayList<>(); + Role role = roleRepository.findById(rolId).orElse(new Role()); + List autorities = role.getAuthorities(); + for (Authority authority : autorities) + { + authorityNames.add(authority.getName()); + } + return authorityNames; + } + +} diff --git a/src/main/java/pedidos/pedidos/core/authz/service/UserService.java b/src/main/java/pedidos/pedidos/core/authz/service/UserService.java new file mode 100644 index 0000000..55e8776 --- /dev/null +++ b/src/main/java/pedidos/pedidos/core/authz/service/UserService.java @@ -0,0 +1,107 @@ +package pedidos.pedidos.core.authz.service; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.stereotype.Service; + +import jakarta.transaction.Transactional; +import pedidos.pedidos.core.authz.entity.Authority; +import pedidos.pedidos.core.authz.entity.Role; +import pedidos.pedidos.core.authz.entity.User; +import pedidos.pedidos.core.authz.repository.UserRepository; + + +@Service +public class UserService implements UserDetailsService { + + @Autowired + UserRepository userRepository; + @Autowired + RoleService roleService; + + BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); + + //Create and update + public User save(User entity){ + + entity.setPassword(encoder.encode(entity.getPassword())); + return userRepository.save(entity); + } + //Read + public User findById(long id){ + return userRepository.findById(id).orElseThrow(); + } + + public User findByUsernameAndPassword(String name, String password){ + return userRepository.findByUsernameAndPassword(name, password); + } + + public User findByUsername(String name){ + return userRepository.findByUsername(name); + } + + //Delete + public void deleteById(long id){ + userRepository.deleteById(id); + } + + public List findAll(){ + List users = userRepository.findAll(); + return users; + } + + @Transactional + @Override + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + + return userRepository.findByUsername(username); + } + + @Transactional + public User getUserWithRolesByUsername(String username) + { + + User user = userRepository.findByUsername(username); + List grantedAuthorities = new ArrayList<>(); + + for (Role role : user.getRoles()) + { + grantedAuthorities.add(new SimpleGrantedAuthority(role.getName())); + } + user.setAuthorities(grantedAuthorities); + return user; + } + + @Transactional + public User getUserWithAuthoritiesByUsername(String username) + { + + User user = userRepository.findByUsername(username); + List grantedAuthorities = new ArrayList<>(); + + for (Role role : user.getRoles()) + { + for (Authority auth : role.getAuthorities()){ + grantedAuthorities.add(new SimpleGrantedAuthority(auth.getName())); + } + } + user.setAuthorities(grantedAuthorities); + return user; + } + + public boolean hasAuthority(String username, String authority){ + return userRepository.hasAuthority(username, authority); + } + + public boolean matchPassword(String passwordIn, String userPassword){ + return encoder.matches(passwordIn, userPassword); + } +} diff --git a/src/main/java/pedidos/pedidos/core/cliente/ClienteController.java b/src/main/java/pedidos/pedidos/core/cliente/ClienteController.java index c8a20b8..1376456 100644 --- a/src/main/java/pedidos/pedidos/core/cliente/ClienteController.java +++ b/src/main/java/pedidos/pedidos/core/cliente/ClienteController.java @@ -1,6 +1,7 @@ package pedidos.pedidos.core.cliente; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; @@ -11,6 +12,10 @@ import org.springframework.web.bind.annotation.PatchMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; + import java.math.BigInteger; import java.util.List; import java.lang.reflect.Field; @@ -19,10 +24,13 @@ import java.util.Map; @RestController @RequestMapping("api/cliente") @CrossOrigin({"*"}) +@Tag(name = "Controlador de Cliente (Tabla cliente)") public class ClienteController { @Autowired ClienteService clienteService; + @PreAuthorize("hasAuthority('Cliente_LeerTodos')") @GetMapping("/") + @Operation(summary = "Obtiene todos los clientes, requiere el permiso Cliente_LeerTodos ") public List findAll(){ return clienteService.findAll(); } @@ -33,6 +41,7 @@ public class ClienteController { } @PostMapping("/") + @PreAuthorize("hasAuthority('Cliente_Crear')") public Cliente save(@RequestBody Cliente entity){ return clienteService.save(entity); } diff --git a/src/main/java/pedidos/pedidos/core/pedidos/DetallePedido.java b/src/main/java/pedidos/pedidos/core/pedidos/DetallePedido.java new file mode 100644 index 0000000..b92d13e --- /dev/null +++ b/src/main/java/pedidos/pedidos/core/pedidos/DetallePedido.java @@ -0,0 +1,24 @@ +package pedidos.pedidos.core.pedidos; + +import java.math.BigDecimal; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.ManyToOne; +import lombok.Data; +import pedidos.pedidos.core.producto.Producto; + +@Data +@Entity +public class DetallePedido { + @Id + @GeneratedValue(strategy = GenerationType.AUTO ) + private Integer id; + + @ManyToOne + private Producto producto; + private Integer cantidad; + private BigDecimal precio; +} diff --git a/src/main/java/pedidos/pedidos/core/pedidos/Pedido.java b/src/main/java/pedidos/pedidos/core/pedidos/Pedido.java new file mode 100644 index 0000000..7611636 --- /dev/null +++ b/src/main/java/pedidos/pedidos/core/pedidos/Pedido.java @@ -0,0 +1,31 @@ +package pedidos.pedidos.core.pedidos; + +import java.util.ArrayList; +import java.util.List; + +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToMany; +import lombok.Data; +import pedidos.pedidos.core.cliente.Cliente; + +@Data +@Entity +public class Pedido { + @Id + @GeneratedValue(strategy = GenerationType.AUTO ) + private Integer id; + + private String numero; + @ManyToOne + private Cliente cliente; + + @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true) + @JoinColumn(name="pedido_id") + private List detalle = new ArrayList<>(); +} diff --git a/src/main/java/pedidos/pedidos/core/pedidos/PedidoController.java b/src/main/java/pedidos/pedidos/core/pedidos/PedidoController.java new file mode 100644 index 0000000..6e0ac3c --- /dev/null +++ b/src/main/java/pedidos/pedidos/core/pedidos/PedidoController.java @@ -0,0 +1,76 @@ +package pedidos.pedidos.core.pedidos; + +import java.lang.reflect.Field; +import java.util.List; +import java.util.Map; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/api/pedido") +@CrossOrigin({"*"}) +public class PedidoController { + + @Autowired + PedidoService service; + + @GetMapping("/{id}/") + public Pedido findById(@PathVariable Integer id){ + return service.findById(id); + } + + @GetMapping("/") + public List findAll(){ + return service.findAll(); + } + + //Create + //Delimitador de acceso (public, private), tipo de dato de retorno, nombre del método, parametros de entrada { Sentencias } + @PostMapping("/") + public Pedido save (@RequestBody Pedido entity ){ + return service.save(entity); + } + + @PutMapping("/") + public Pedido update (@RequestBody Pedido entity){ + return service.save(entity); + } + + @DeleteMapping("/{id}/") + public void deleteById(@PathVariable Integer id){ + service.deleteById(id); + } + + @PatchMapping("/{id}/") + public Pedido partialUpdate(@PathVariable Integer id, @RequestBody Map fields){ + + Pedido entity = findById(id); + + // itera sobre los campos que se desean actualizar + for (Map.Entry field : fields.entrySet()) { + String fieldName = field.getKey(); + Object fieldValue = field.getValue(); + + // utiliza reflection para establecer el valor del campo en la entidad + try { + Field campoEntidad = Pedido.class.getDeclaredField(fieldName); + campoEntidad.setAccessible(true); + campoEntidad.set(entity, fieldValue); + } catch (NoSuchFieldException | IllegalAccessException ex) { + // maneja la excepción si ocurre algún error al acceder al campo + } + } + return update(entity); + } + +} diff --git a/src/main/java/pedidos/pedidos/core/pedidos/PedidoRepository.java b/src/main/java/pedidos/pedidos/core/pedidos/PedidoRepository.java new file mode 100644 index 0000000..c6e14ec --- /dev/null +++ b/src/main/java/pedidos/pedidos/core/pedidos/PedidoRepository.java @@ -0,0 +1,10 @@ +package pedidos.pedidos.core.pedidos; + +import java.util.List; + +import org.springframework.data.repository.CrudRepository; + +public interface PedidoRepository extends CrudRepository { + + List findAll(); +} diff --git a/src/main/java/pedidos/pedidos/core/pedidos/PedidoService.java b/src/main/java/pedidos/pedidos/core/pedidos/PedidoService.java new file mode 100644 index 0000000..2a2c92b --- /dev/null +++ b/src/main/java/pedidos/pedidos/core/pedidos/PedidoService.java @@ -0,0 +1,28 @@ +package pedidos.pedidos.core.pedidos; + +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class PedidoService { + + @Autowired + PedidoRepository repository; + + public Pedido save( Pedido entity){ + return repository.save(entity); + } + + public void deleteById(Integer id){ + repository.deleteById(id); + } + + public Pedido findById(Integer id){ + return repository.findById(id).orElse(null); + } + + public List findAll(){ + return repository.findAll(); + } +} \ No newline at end of file diff --git a/src/main/resources/application-prod.properties b/src/main/resources/application-prod.properties new file mode 100644 index 0000000..a883d7a --- /dev/null +++ b/src/main/resources/application-prod.properties @@ -0,0 +1,6 @@ +spring.datasource.url=jdbc:postgresql://db:5432/pedidosdb +spring.datasource.username=postgres +spring.datasource.password=postgres +spring.jpa.hibernate.ddl-auto=update +#spring.jpa.show-sql=true +server.port=8081 \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index a883d7a..f04ccfb 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,6 +1,7 @@ -spring.datasource.url=jdbc:postgresql://db:5432/pedidosdb +spring.datasource.url=jdbc:postgresql://localhost:5432/pedidosdb spring.datasource.username=postgres spring.datasource.password=postgres spring.jpa.hibernate.ddl-auto=update #spring.jpa.show-sql=true +#spring.sql.init.mode=always server.port=8081 \ No newline at end of file diff --git a/src/main/resources/data.sql b/src/main/resources/data.sql new file mode 100644 index 0000000..a0f5f34 --- /dev/null +++ b/src/main/resources/data.sql @@ -0,0 +1,54 @@ +INSERT INTO authorities (name, endpoint) values ('User_Write', 'POST:/api/user/'); +INSERT INTO authorities (name, endpoint) values ('User_Read', 'GET:/api/user/'); +INSERT INTO authorities (name, endpoint) values ('UserById_Read', 'GET:/api/user/{id}/'); +INSERT INTO authorities (name, endpoint) values ('User_Delete', 'DELETE:/api/user/{id}/'); +INSERT INTO authorities (name, endpoint) values ('User_Update', 'PUT:/api/user/{id}/'); +INSERT INTO authorities (name, endpoint) values ('User_PartialUpdate', 'PATCH:/api/user/{id}/'); + +INSERT INTO authorities (name, endpoint) values ('Role_Write', 'POST:/api/role/'); +INSERT INTO authorities (name, endpoint) values ('Role_Read', 'GET:/api/role/'); +INSERT INTO authorities (name, endpoint) values ('RoleById_Read', 'GET:/api/role/{id}/'); +INSERT INTO authorities (name, endpoint) values ('Role_Delete', 'DELETE:/api/role/{id}/'); +INSERT INTO authorities (name, endpoint) values ('Role_Update', 'PUT:/api/role/{id}/'); +INSERT INTO authorities (name, endpoint) values ('Role_PartialUpdate', 'PATCH:/api/role/'); + +INSERT INTO authorities (name, endpoint) values ('Authority_Write', 'POST:/api/authority/'); +INSERT INTO authorities (name, endpoint) values ('Authority_Read', 'GET:/api/authority/'); +INSERT INTO authorities (name, endpoint) values ('AuthorityById_Read', 'GET:/api/authority/{id}/'); +INSERT INTO authorities (name, endpoint) values ('Authority_Delete', 'DELETE:/api/authority/{id}/'); +INSERT INTO authorities (name, endpoint) values ('Authority_Update', 'PUT:/api/authority/{id}/'); +INSERT INTO authorities (name, endpoint) values ('Authority_PartialUpdate', 'PATCH:/api/authority/{id}/'); +INSERT INTO authorities (name, endpoint) values ('AuthorityByUser_Read', 'GET:/api/authority/byuser/{id}/'); + +INSERT INTO authorities (name, endpoint) values ('Customer_Write', 'POST:/api/cliente/'); +INSERT INTO authorities (name, endpoint) values ('Customer_Read', 'GET:/api/cliente/'); +INSERT INTO authorities (name, endpoint) values ('CustomerById_Read', 'GET:/api/cliente/{id}/'); +INSERT INTO authorities (name, endpoint) values ('Customer_Delete', 'DELETE:/api/cliente/{id}'); +INSERT INTO authorities (name, endpoint) values ('Customer_Update', 'PUT:/api/cliente/{id}'); +INSERT INTO authorities (name, endpoint) values ('Customer_PartialUpdate', 'PATCH:/api/cliente/{id}'); + +INSERT INTO authorities (name, endpoint) values ('Product_Write', 'POST:/api/product/'); +INSERT INTO authorities (name, endpoint) values ('Product_Read', 'GET:/api/product/'); +INSERT INTO authorities (name, endpoint) values ('ProductById_Read', 'GET:/api/product/{id}/'); +INSERT INTO authorities (name, endpoint) values ('Product_Delete', 'DELETE:/api/product/{id}/'); +INSERT INTO authorities (name, endpoint) values ('Product_Update', 'PUT:/api/product/{id}/'); +INSERT INTO authorities (name, endpoint) values ('Product_PartialUpdate', 'PATCH:/api/product/{id}/'); + +INSERT INTO authorities (name, endpoint) values ('Invoice_Write', 'POST:/api/factura/'); +INSERT INTO authorities (name, endpoint) values ('Invoice_Read', 'GET:/api/factura/'); +INSERT INTO authorities (name, endpoint) values ('InvoiceById_Read', 'GET:/api/factura/{id}/'); +INSERT INTO authorities (name, endpoint) values ('Invoice_Delete', 'DELETE:/api/factura/{id}/'); +INSERT INTO authorities (name, endpoint) values ('Invoice_Update', 'PUT:/api/factura/{id}/'); +INSERT INTO authorities (name, endpoint) values ('Invoice_PartialUpdate', 'PATCH:/api/factura/{id}/'); +INSERT INTO authorities (name, endpoint) values ('InvoicePdf_Read', 'GET:/api/factura/pdf/{id}/'); + + +INSERT INTO roles (name) values ('ROLE_ADMIN'); +INSERT INTO roles (name) values ('ROLE_ASESOR'); +INSERT INTO roles (name) values ('ROLE_FACTURADOR'); + +INSERT INTO roles_authorities (role_id, authority_id) (select (SELECT id FROM roles where name = 'ROLE_ADMIN') AS role_id, e.id from authorities e ); + +INSERT INTO users (name, username, password, looked, expired, enabled) VALUES ('Admin', 'admin', '$2a$10$TwROhi2MZsOTt8igkE7Yyec0WfjK7NlgdX9apOu0b6cY4SxzHLvCq', false, false, true); + +INSERT INTO users_roles (user_id, role_id) VALUES ((SELECT id FROM users where username = 'admin'), (SELECT id FROM roles where name = 'ROLE_ADMIN')); \ No newline at end of file