package es.tatvil.taiageweb.servicio; import es.tatvil.taiageweb.modelo.Usuario; import es.tatvil.taiageweb.repositorio.UsuarioRepository; 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.password.PasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.stream.Collectors; @Service public class UsuarioService implements UserDetailsService { private final UsuarioRepository repo; private final PasswordEncoder encoder; public UsuarioService(UsuarioRepository repo, PasswordEncoder encoder) { this.repo = repo; this.encoder = encoder; } // ── Spring Security ────────────────────────────────────── @Override public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException { Usuario u = repo.findByEmail(email) .orElseThrow(() -> new UsernameNotFoundException("Usuario no encontrado: " + email)); var authorities = u.getRoles().stream() .map(SimpleGrantedAuthority::new) .collect(Collectors.toList()); return new org.springframework.security.core.userdetails.User( u.getEmail(), u.getPassword(), u.isHabilitado(), // enabled true, // accountNonExpired true, // credentialsNonExpired true, // accountNonLocked authorities ); } // ── Auto-registro (pendiente de activación) ────────────── @Transactional public void registrar(String email, String passwordPlana) { if (repo.existsByEmail(email)) { throw new IllegalArgumentException("El email ya está registrado"); } if (passwordPlana.length() < 8) { throw new IllegalArgumentException("La contraseña debe tener al menos 8 caracteres"); } Usuario u = new Usuario(); u.setEmail(email); u.setPassword(encoder.encode(passwordPlana)); u.setHabilitado(false); // pendiente de activación por admin u.setRoles(new HashSet<>(Set.of("ROLE_USER"))); repo.save(u); } // ── Consultas ──────────────────────────────────────────── public List listarTodos() { return repo.findAll(); } // ── Acciones de admin ──────────────────────────────────── @Transactional public void toggleHabilitado(Long id) { Usuario u = repo.findById(id).orElseThrow(); u.setHabilitado(!u.isHabilitado()); } @Transactional public void toggleRolPagado(Long id) { Usuario u = repo.findById(id).orElseThrow(); if (u.getRoles().contains("ROLE_PAGADO")) { u.getRoles().remove("ROLE_PAGADO"); } else { u.getRoles().add("ROLE_PAGADO"); } } /** Concede acceso al curso tras un pago confirmado por Stripe (nunca quita el rol) */ @Transactional public void darAccesoPagado(Long id) { Usuario u = repo.findById(id).orElseThrow(); u.getRoles().add("ROLE_PAGADO"); u.setHabilitado(true); } /** El admin crea directamente un usuario ya activo */ @Transactional public void crearPorAdmin(String email, String passwordPlana, boolean pagado) { if (repo.existsByEmail(email)) { throw new IllegalArgumentException("El email ya está registrado"); } Usuario u = new Usuario(); u.setEmail(email); u.setPassword(encoder.encode(passwordPlana)); u.setHabilitado(true); Set roles = new HashSet<>(); roles.add("ROLE_USER"); if (pagado) roles.add("ROLE_PAGADO"); u.setRoles(roles); repo.save(u); } @Transactional public void eliminar(Long id) { repo.deleteById(id); } }