clase de autenticacion, autorización, documentacion y relaciones one to many

main
Freddy Heredia 2 years ago
parent c6c4be7c98
commit d023288574

@ -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') {

@ -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<? extends GrantedAuthority> 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\"}";
}
}
}

@ -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;
}
}

@ -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<String,Object> 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()));
}
}

@ -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();
}
}

@ -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<Authority> 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<Authority> findByUsename(@PathVariable String username){
return authorityService.findByUsername(username);
}
}

@ -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<Role> 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);
}
}

@ -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<User> 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<String> 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<Authority> 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");
}
}

@ -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;
}

@ -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<Authority> authorities;
}

@ -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<Role> roles;
@Transient
private Collection<? extends GrantedAuthority> authorities;
@Override
public Collection<? extends GrantedAuthority> 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;
}
}

@ -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<Authority, Long> {
List<Authority> 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<Authority> findByUsername(String username);
List<Authority> findByNameIgnoreCaseLike(String term);
}

@ -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 <Role, Long> {
List<Role> findAll();
}

@ -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 <User, Long>{
List<User> 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);
}

@ -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<Authority> findAll(){
return authorityRepository.findAll();
}
public List<Authority> findByUsername(String username){
return authorityRepository.findByUsername(username);
}
public List<Authority> findByName(String term){
return authorityRepository.findByNameIgnoreCaseLike(term+"%");
}
}

@ -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<Role> findAll(){
return roleRepository.findAll();
}
public List<String> getAuthoritiesByRolid(long rolId)
{
List<String> authorityNames = new ArrayList<>();
Role role = roleRepository.findById(rolId).orElse(new Role());
List<Authority> autorities = role.getAuthorities();
for (Authority authority : autorities)
{
authorityNames.add(authority.getName());
}
return authorityNames;
}
}

@ -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<User> findAll(){
List<User> 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<GrantedAuthority> 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<GrantedAuthority> 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);
}
}

@ -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<Cliente> 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);
}

@ -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;
}

@ -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<DetallePedido> detalle = new ArrayList<>();
}

@ -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<Pedido> 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<String, Object> fields){
Pedido entity = findById(id);
// itera sobre los campos que se desean actualizar
for (Map.Entry<String, Object> 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);
}
}

@ -0,0 +1,10 @@
package pedidos.pedidos.core.pedidos;
import java.util.List;
import org.springframework.data.repository.CrudRepository;
public interface PedidoRepository extends CrudRepository <Pedido, Integer> {
List<Pedido> findAll();
}

@ -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<Pedido> findAll(){
return repository.findAll();
}
}

@ -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

@ -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

@ -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'));
Loading…
Cancel
Save