package br.gov.servicos.editor.usuarios.recuperarsenha;
import br.gov.servicos.editor.usuarios.Usuario;
import br.gov.servicos.editor.usuarios.UsuarioInexistenteException;
import br.gov.servicos.editor.usuarios.UsuarioService;
import br.gov.servicos.editor.usuarios.token.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
import java.time.Clock;
import java.time.LocalDateTime;
import java.util.Optional;
import static java.lang.Long.valueOf;
@Component
public class RecuperacaoSenhaService {
@Autowired
private GeradorToken geradorToken;
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired
private TokenRepository tokens;
@Autowired
private UsuarioService usuarioService;
@Autowired
private RecuperacaoSenhaValidator validator;
@Value("${eds.max-tentativas-token}")
private int maxTentativasToken;
@Value("${eds.token.desabilitarUsuario}")
private boolean desabilitarUsuarioAoCriarToken = true;
private final Clock clock = Clock.systemUTC();
public String gerarTokenParaUsuario(String usuarioId) {
String token = geradorToken.gerar();
Token tokenRecuperacaoSenha = new Token()
.withUsuario(new Usuario().withId(valueOf(usuarioId)))
.withDataCriacao(LocalDateTime.now(clock))
.withTentativasSobrando(maxTentativasToken)
.withToken(passwordEncoder.encode(token));
tokens.deleteByUsuarioId(valueOf(usuarioId));
tokens.save(tokenRecuperacaoSenha);
if (desabilitarUsuarioAoCriarToken) {
usuarioService.desabilitarUsuario(usuarioId);
}
return token;
}
public Usuario trocarSenha(FormularioRecuperarSenha formulario) throws CpfTokenInvalido, TokenExpirado {
Token token = findLatestTokenByUsuarioId(formulario.getUsuarioId());
Usuario usuario = token.getUsuario();
Optional<TokenError> tokenError = validator.hasError(formulario, token);
if (!tokenError.isPresent()) {
Usuario usuarioComSenhaNova = usuario
.withSenha(passwordEncoder.encode(formulario.getCamposSenha().getSenha()))
.withHabilitado(true);
usuarioService.save(usuarioComSenhaNova);
tokens.delete(token.getId());
return usuarioComSenhaNova;
}
if (tokenError.get().equals(TokenError.INVALIDO)) {
Token novoToken = token.decrementarTentativasSobrando();
tokens.save(novoToken);
throw new CpfTokenInvalido(novoToken.getTentativasSobrando());
}
throw new TokenExpirado();
}
private Token findLatestTokenByUsuarioId(Long usuarioId) {
Iterable<Token> tokensUsuario = tokens.findByUsuarioId(usuarioId);
if (!tokensUsuario.iterator().hasNext()) {
throw new UsuarioInexistenteException();
}
return tokensUsuario.iterator().next();
}
}