@Entity
@DiscriminatorValue("ALUNO")
public class Aluno extends Usuario {

} @Entity
@DiscriminatorValue("PROFESSOR")
public class Professor extends Aluno {

} @Entity
public class Turma extends Identity<Integer> {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seq_turma")
    @SequenceGenerator(name = "seq_turma", sequenceName = "seq_turma", allocationSize = 1, initialValue = 1)
    private Integer    id;

    @Column(length = 50)
    private String     nome;

    @ManyToMany
    @CollectionTable
    private Set<Aluno> alunos;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    public Set<Aluno> getAlunos() {
        return alunos;
    }

    public void setAlunos(Set<Aluno> alunos) {
        this.alunos = alunos;
    }

} @Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "PERFIL", length = 50)
public abstract class Usuario extends Identity<Integer> {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seq_usuario")
    @SequenceGenerator(name = "seq_usuario", sequenceName = "seq_usuario", allocationSize = 1, initialValue = 1)
    private Integer    id;

    @Column(unique = true, length = 50)
    private String     idFacebook;

    @Column(unique = true, length = 50)
    private String     idGoogle;

    @Column(unique = true, length = 100)
    private String     email;

    @Column(length = 100)
    private String     nome;

    private Boolean    ativo;

    @Column(unique = true, length = 50)
    private String     convite;

    @Enumerated(EnumType.STRING)
    @Column(length = 50)
    private RedeSocial redeSocial;

    @Column(length = 50)
    private String     senha;

    @ManyToOne
    private Usuario    convidadoPor;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    public Boolean getAtivo() {
        return ativo;
    }

    public void setAtivo(Boolean ativo) {
        this.ativo = ativo;
    }

    public String getConvite() {
        return convite;
    }

    public void setConvite(String convite) {
        this.convite = convite;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public RedeSocial getRedeSocial() {
        return redeSocial;
    }

    public void setRedeSocial(RedeSocial redeSocial) {
        this.redeSocial = redeSocial;
    }

    public String getIdFacebook() {
        return idFacebook;
    }

    public void setIdFacebook(String idFacebook) {
        this.idFacebook = idFacebook;
    }

    public String getSenha() {
        return senha;
    }

    public void setSenha(String senha) {
        this.senha = senha;
    }

    public Usuario getConvidadoPor() {
        return convidadoPor;
    }

    public void setConvidadoPor(Usuario convidadoPor) {
        this.convidadoPor = convidadoPor;
    }

    public String getIdGoogle() {
        return idGoogle;
    }

    public void setIdGoogle(String idGoogle) {
        this.idGoogle = idGoogle;
    }

} public enum RedeSocial {

    FACEBOOK, GOOGLE;

} @SuppressWarnings("serial")
public class LeitoorException extends Exception {

    public LeitoorException(String message, Throwable cause) {
        super(message, cause);
    }

    public LeitoorException(String message) {
        super(message);
    }

    public static LeitoorException conviteInvalidoException(String convite) {
        return new LeitoorException("Este convite não possui validade em nosso sistema:" + convite);
    }

    public static LeitoorException contaInvalidaException(String mensagem) {
        return new LeitoorException(mensagem);
    }

    public static LeitoorException autenticacaoException(String mensagem) {
        return new LeitoorException(mensagem);
    }

} public class Cadastro {

    @NotEmpty
    @EmailValido
    private String email;

    @Pattern(regexp = "\\S+", message = "Não deve conter espaços em branco")
    @Size(min = 8, max = 50)
    private String senha;

    @NotEmpty
    private String repetirSenha;

    @NotEmpty
    private String nomeCompleto;

    private String convite;

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getSenha() {
        return senha;
    }

    public void setSenha(String senha) {
        this.senha = senha;
    }

    public String getRepetirSenha() {
        return repetirSenha;
    }

    public void setRepetirSenha(String repetirSenha) {
        this.repetirSenha = repetirSenha;
    }

    public String getNomeCompleto() {
        return nomeCompleto;
    }

    public void setNomeCompleto(String nomeCompleto) {
        this.nomeCompleto = nomeCompleto;
    }

    public String getConvite() {
        return convite;
    }

    public void setConvite(String convite) {
        this.convite = convite;
    }

} public interface AlunoRepository extends EntityRepository<Aluno, Integer> {

    Aluno findByEmail(String email);

    @Query("select a from Aluno as a")
    List<Aluno> findAll();

} public interface TarefaEnviadaRepository extends EntityRepository<TarefaEnviada, Integer> {

    @Modifying
    @Query("update TarefaEnviada te set te.aluno = ?1 where te.aluno = ?2")
    void moverTarefasConvidadoParaUsuario(Aluno usuario, Aluno convidado);
    
    List<TarefaEnviada> findByAluno(Aluno aluno);
    
    List<TarefaEnviada> findByTarefa(Tarefa tarefa);
    
    @Query("select l from Leitura l where l.tarefaEnviada.tarefa = ?1")
    List<Leitura> findLeiturasByTarefa(Tarefa tarefa);
    

} public interface TurmaRepository extends EntityRepository<Turma, Integer> {

    List<Turma> findByAlunosIn(Aluno convidado);
    
    @Query(value="select distinct t.turma from Tarefa t where t.professor = ?1 ")
    List<Turma> findByTurmaByProfessor(Professor p);

} public interface UsuarioRepository extends EntityRepository<Usuario, Integer> {

    Usuario findByConvite(String convite);

    Usuario findByEmail(String email);

    Usuario findByIdFacebook(String id);

    Usuario findByIdGoogle(String id);

    Usuario findByEmailAndSenha(String email, String senha);

    @Modifying
    @Query(nativeQuery = true, value = "update usuario set perfil = 'PROFESSOR' where id = ?1")
    int tornarProfessor(Integer id);

} public interface AutenticacaoService {

    RegraNegocioException CONVITE_INVALIDO_EXCEPTION                    = new RegraNegocioException("Esse convite não é válido");

    RegraNegocioException SENHAS_DIFERENTES_EXCEPTION                   = new RegraNegocioException("As senhas digitadas são diferentes");

    RegraNegocioException USUARIO_INATIVO_EXCEPTION                     = new RegraNegocioException(
                                                                            "Seu usuário está inativo e não pode mais ser utilizado");

    RegraNegocioException USUARIO_INEXISTENTE_EXCEPTION                 = new RegraNegocioException();

    RegraNegocioException SENHA_INCORRETA_EXCEPTION                     = new RegraNegocioException("A senha digitada é incorreta");

    RegraNegocioException SENHA_VAZIA_EXCEPTION                         = new RegraNegocioException("A senha deve ser informada");

    RegraNegocioException RECUPERAR_SENHA_EMAIL_VAZIO_EXCEPTION         = new RegraNegocioException("O e-mail deve ser informado");

    RegraNegocioException RECUPERAR_SENHA_CONTA_CONVIDADA_EXCEPTION     = new RegraNegocioException(
                                                                            "Você já foi convidado, crie um cadastro ou conecte-se com o facebook!");

    RegraNegocioException RECUPERAR_SENHA_CONTA_TIPO_FACEBOOK_EXCEPTION = new RegraNegocioException(
                                                                            "A conta informada é vinculada ao facebook, por favor conecte-se com facebook!");

    RegraNegocioException RECUPERAR_SENHA_CONTA_INEXISTENTE_EXCEPTION   = new RegraNegocioException(
                                                                            "Não existe usuário com o e-mail informado");

    Professor getProfessorAutenticado();

    Aluno getAlunoAutenticado();

    Usuario getUsuarioAutenticado();

    Usuario criarUsuarioPorCadastro(Cadastro cadastro) throws LeitoorException;

    boolean isUsuarioAutenticado();

    boolean isProfessorAutenticado();

    boolean isAlunoAutenticado();

    Usuario obterUsuarioViaFacebook(User userFacebook, String convite) throws LeitoorException;

    void autenticarUsuario(Usuario usuario);

    Usuario autenticarUsuarioPorCadastro(String email, String senha) throws LeitoorException;

    String getNomeUsuarioAutenticado();

    String getEmailUsuarioAutenticado();

    Result<Void> convidarProfessores(String emails, Professor professor);

    String recuperarSenha(String email) throws LeitoorException;

    Usuario obterUsuarioViaGoogle(Userinfoplus userInfoPlus, String convite) throws LeitoorException;

} public class Result<E> {

    public enum Status {
        SUCCESS, FAILURE
    }

    private final String    message;
    private final Status    status;
    private final E         value;
    private final Violation violation;

    private Result(String message, E value) {
        this.message = message;
        this.status = Status.SUCCESS;
        this.value = value;
        this.violation = null;
    }

    private Result(Violation violation, E value) {
        this.message = violation.getMessage();
        this.status = Status.FAILURE;
        this.value = value;
        this.violation = violation;
    }

    public static final <E> Result<E> success(String message) {
        return new Result<E>(message, null);
    }

    public static final <E> Result<E> success(String message, E value) {
        return new Result<E>(message, value);
    }

    public static final <E> Result<E> failure(Violation violation) {
        return new Result<E>(violation, null);
    }

    public static final <E> Result<E> failure(Violation violation, E value) {
        return new Result<E>(violation, value);
    }

    public String getMessage() {
        return message;
    }

    public boolean isSuccess() {
        return status == Status.SUCCESS;
    }

    public boolean isFailure() {
        return status == Status.FAILURE;
    }

    public boolean hasValue() {
        return Has.content(value);
    }

    public E getValue() {
        return value;
    }

    public Violation getViolation() {
        return violation;
    }

    public Status getStatus() {
        return status;
    }

    public boolean failsAt(Violation violation, Violation... violations) {
        if (this.violation == null || this.status == Status.SUCCESS) {
            return false;
        }

        if (this.violation == violation || violation.equals(this.violation)) {
            return true;
        }

        if (violations != null && violations.length > 0) {
            for (Violation v : violations) {
                if (this.violation == v || this.violation.equals(v)) {
                    return true;
                }
            }
        }

        return false;
    }

}
import java.util.UUID;
import javax.inject.Inject;
import javax.inject.Named;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.springframework.beans.BeanUtils;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
import org.springframework.transaction.annotation.Transactional;
import br.com.delogic.csa.manager.EmailManager;
import br.com.delogic.csa.manager.email.EmailAddress;
import br.com.delogic.csa.manager.email.EmailContent;
import br.com.delogic.jfunk.Each;
import br.com.delogic.jfunk.ForEach;
import br.com.delogic.jfunk.Has;
import br.com.delogic.leitoor.entidade.Aluno;
import br.com.delogic.leitoor.entidade.Professor;
import br.com.delogic.leitoor.entidade.Turma;
import br.com.delogic.leitoor.entidade.Usuario;
import br.com.delogic.leitoor.entidade.enums.RedeSocial;
import br.com.delogic.leitoor.exception.LeitoorException;
import br.com.delogic.leitoor.model.Cadastro;
import br.com.delogic.leitoor.repository.AlunoRepository;
import br.com.delogic.leitoor.repository.TarefaEnviadaRepository;
import br.com.delogic.leitoor.repository.TurmaRepository;
import br.com.delogic.leitoor.repository.UsuarioRepository;
import br.com.delogic.leitoor.service.AutenticacaoService;
import br.com.delogic.leitoor.util.Result;
import com.google.api.services.oauth2.model.Userinfoplus;
import com.restfb.types.User;
package br.com.delogic.leitoor.service.impl;






public class AutenticacaoServiceImpl implements AutenticacaoService {

    @Inject
    private HttpSession             session;

    @Inject
    private HttpServletRequest      request;

    @Inject
    @Named("authenticationManager")
    private AuthenticationManager   authenticationManager;

    @Inject
    private AlunoRepository         alunoRepository;

    @Inject
    private UsuarioRepository       usuarioRepository;

    @Inject
    private TarefaEnviadaRepository tarefaEnviadaRepository;

    @Inject
    private EmailManager            emailManager;

    @Inject
    private TurmaRepository         turmaRepository;